Multithreaded AES encryption RunWorkerCompleted event never gets called - c#

I am trying to achieve multithreaded AES encryption using Backgroundworker to get the events done. First I read the buffer send it to doworker event. That writes the inbuffer to outbuffer encrypted after the thread is done it needs to write in the RunWorkerCompleted method but it never gets called.
However when I slowly debug using a messagebox, the function fires up! successfully giving me my encrypted file. I don't understand any of this I would appreciate if somebody could help me how to translate this to a threadpool? or maybe explain why it doesn't call runworkercomplete when it is done because it show me the messagebox in the doworker event but not in the runworkercomplete event???
static List<BackgroundWorker> listWorkers = new List<BackgroundWorker>();
static List<BackgroundWorker> listFreeWorkers = new List<BackgroundWorker>();
static FileStream fsIn;
static string file;
static byte[] key;
const int BLOCK_SIZE = 1000;
static FileStream outFile;
public static void EncryptFile(string inputFile, string outputFile, string sKey, String privateKey, ProgressBar progress)
{
String fileName = inputFile;
fileName = "\\" + fileName.Split('\\').Last();
var progres = new Progress<int>(value => progress.Value = value);
file = outputFile + fileName;
fsIn = new FileStream(inputFile, FileMode.Open);
outFile = new FileStream(file, FileMode.Create);
key = new UnicodeEncoding().GetBytes(sKey);
for (int t = 0; t < 4; t++)
{
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
listWorkers.Add(worker);
listFreeWorkers.Add(worker);
}
FileInfo fileInfo = new FileInfo(inputFile);
double numBlocks = Math.Ceiling(((double)fileInfo.Length) / BLOCK_SIZE);
int ixCurrentBlock = 0;
while (ixCurrentBlock < numBlocks)
{
if (listFreeWorkers.Count > 0)
{
BackgroundWorker freeWorker = listFreeWorkers[0];
listFreeWorkers.Remove(freeWorker);
int bytes;
if (ixCurrentBlock < numBlocks - 1)
{
byte[] buffer = new byte[BLOCK_SIZE];
bytes = fsIn.Read(buffer, 0, BLOCK_SIZE);
freeWorker.RunWorkerAsync(Tuple.Create(ixCurrentBlock * BLOCK_SIZE, buffer));
}
else //special handling for last block
{
int size = (int)(fileInfo.Length - ixCurrentBlock * BLOCK_SIZE);
byte[] buffer = new byte[size];
bytes = fsIn.Read(buffer, 0, size);
freeWorker.RunWorkerAsync(Tuple.Create(0, buffer));
}
ixCurrentBlock++;
}
else
{
}
}
var hasAllThreadsFinished1 = (from worker in listWorkers
where worker.IsBusy
select worker).ToList().Count;
while (hasAllThreadsFinished1 != 0)
{
hasAllThreadsFinished1 = (from worker in listWorkers
where worker.IsBusy
select worker).ToList().Count;
}
fsIn.Close();
outFile.Close();
byte[] hash = Hashing.HashFile(outputFile + fileName, privateKey);
File.WriteAllBytes(outputFile + "\\Hashing.txt", hash);
}
private static void worker_DoWork(object sender, DoWorkEventArgs e)
{
Tuple<int, byte[]> t = e.Argument as Tuple<int, byte[]>;
//int blockIndex = (int)t.Item1;
byte[] inBuffer = (byte[])t.Item2;
byte[] outBuffer;
MessageBox.Show("Started");
using (MemoryStream outStream = new MemoryStream())
{
RijndaelManaged RMCrypto = new RijndaelManaged();
using (CryptoStream cs = new CryptoStream(outStream,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write))
{
// I want to write inbuffer non encrypted to outbuffer encrypted.
cs.Write(inBuffer, 0, inBuffer.Length);
}
outBuffer = outStream.ToArray();
}
e.Result = Tuple.Create(0, outBuffer);
MessageBox.Show("done function");
}
static Object pen = new Object();
private static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done");
Tuple<int, byte[]> t = e.Result as Tuple<int, byte[]>;
//int blockIndex = (int)t.Item1;
byte[] buffer = (byte[])t.Item2;
bool b = true;
while (b)
{
lock (pen)
{
outFile.Write(buffer, 0, buffer.Length);
listFreeWorkers.Add((BackgroundWorker)sender);
MessageBox.Show("Done");
b = false;
}
}
}
UPDATE:
The error tends to be when 4 threads are running at the same time. They simply get stuck I tested using a messageBox here.
using (CryptoStream cs = new CryptoStream(outStream,
RMCrypto.CreateEncryptor(key, key),
CryptoStreamMode.Write))
{
// I want to write inbuffer non encrypted to outbuffer encrypted.
cs.Write(inBuffer, 0, inBuffer.Length);
}
outBuffer = outStream.ToArray();
MessageBox.Show(outBuffer[0] + " done function");
Will give me the encrypt file. This makes no sense why can't my threads run the dowork method at the same time :(?

As you don't specify a Block cipher mode for RijndaelManaged() you get the default CBC mode. In CBC mode each block encrypted / decrypted are made dependent of the previous block. This prevents encrypt and decrypt of the individual blocks to be done in parallel.

Related

How to execute decrypted file automatically without specifying it's path?

Need help T_T
I'm running the code below to Decrypt an exe File I'm trying to Run it and Automatically execute the Decrypted file would it be possible to execute it without saving it's data to the disk?
I'm also trying to run it without the need of specifying the encrypted file name but have no idea what changes need to be done for this to happen or if it's even possible.
FileInfo encFile = new FileInfo("7GNTBBASDADASDASDASDASDASDASDASDSW7VBKGUX5TB5XBXDG3W4DWC6K6JBMTG7C2OYEHNPSN4PE6JYLJDUA"); // < File name in the current directory
const int ReadBufferSize = 64 * 1024;
static void Main(string[] args)
{
{
// DECRYPTION
FileInfo encFile = new FileInfo("7GNTBBASDADASDASDASDASDASDASDASDSW7VBKGUX5TB5XBXDG3W4DWC6K6JBMTG7C2OYEHNPSN4PE6JYLJDUA"); // < File name in the current directory
byte[] iv = Convert.FromBase64String("SWW/HAWEWQF/F2d/WrSSA==");
byte[] key = Convert.FromBase64String("ASDSADSAwwqIM221vASXG1221nqk=");
// DECRYPTION
// DECRYPTION
using (FileStream inp = encFile.OpenRead())
using (AesManaged aes = new AesManaged())
{
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
aes.IV = iv;
aes.Key = key;
using (CryptoStream cs = new CryptoStream(inp, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
// crypted file structure: {name length x4}{full file name}{data length x8}{data}{sha512 hash of data x64}
byte[] nameLengthBits = new byte[2];
if (cs.Read(nameLengthBits, 0, 2) != 2)
{
Console.Error.WriteLine("ERROR: Failed reading file name size");
return;
}
ushort nameLength = BitConverter.ToUInt16(nameLengthBits, 0);
byte[] originalName = new byte[nameLength];
if (cs.Read(originalName, 0, nameLength) != nameLength)
{
Console.Error.WriteLine("ERROR: Failed reading file name");
return;
}
string fileName = Encoding.UTF8.GetString(originalName);
byte[] dataLengthBits = new byte[8];
if (cs.Read(dataLengthBits, 0, dataLengthBits.Length) != dataLengthBits.Length)
{
Console.Error.WriteLine("ERROR: Failed reading data length");
return;
}
long dataLength = BitConverter.ToInt64(dataLengthBits, 0);
string outputFileName = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileName(fileName));
if (File.Exists(outputFileName))
{
}
byte[] decryptedHash;
long totalRead = 0;
using (FileStream outputStream = new FileStream(outputFileName, FileMode.CreateNew, FileAccess.Write, FileShare.Read))
using (SHA512Managed hasher = new SHA512Managed())
{
byte[] buffer = new byte[ReadBufferSize];
long bytesRemaining = dataLength;
while (bytesRemaining > 0)
{
int readingThisRound = ReadBufferSize < bytesRemaining ? ReadBufferSize : (int)bytesRemaining;
int bytesRead = cs.Read(buffer, 0, readingThisRound);
totalRead += bytesRead;
// dump decrypted data to file
outputStream.Write(buffer, 0, bytesRead); }
//
//
hasher.TransformFinalBlock(buffer, 0, 0);
decryptedHash = hasher.Hash;}
byte[] originalHashBits = new byte[64];
if (cs.Read(originalHashBits, 0, originalHashBits.Length) != originalHashBits.Length) using (FileStream outputStream = new FileStream(outputFileName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
}
if (originalHashBits.SequenceEqual(decryptedHash))

Converting stream encryption method from .NET to RT

I'm trying to convert Encryption/Decryption methods from managed .NET to WinRT version for use in Windows Store app. The managed .NET encryption methods are already used largely in production, so the assumption is they work correctly.
This is the managed .NET encryption method:
public static byte[] iv = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
public static void EncryptFile(string sInputFilename, string sOutputFilename, string sKey)
{
FileStream fsInput = null;
FileStream fsOutput = null;
CryptoStream cryptostream = null;
try
{
#region Prep
fsInput = new FileStream(sInputFilename, FileMode.Open, FileAccess.Read);
fsOutput = new FileStream(sOutputFilename, FileMode.Create, FileAccess.Write);
var cryptoDes = new DESCryptoServiceProvider { IV = iv, Key = Convert.FromBase64String(sKey), Mode = CipherMode.CBC };
var desEncrypt = cryptoDes.CreateEncryptor();
#endregion
cryptostream = new CryptoStream(fsOutput, desEncrypt, CryptoStreamMode.Write);
long startIndex = 0;
var bytearrayinput = new byte[64];
var byteCount = bytearrayinput.Length;
while (startIndex < fsInput.Length)
{
if (fsInput.Length - startIndex < byteCount)
{
byteCount = (int)(fsInput.Length - startIndex);
}
fsInput.Read(bytearrayinput, 0, byteCount);
cryptostream.Write(bytearrayinput, 0, byteCount);
startIndex += byteCount;
}
cryptostream.FlushFinalBlock();
}
finally
{
if (fsInput != null) { fsInput.Close(); }
if (cryptostream != null) { cryptostream.Close(); }
if (fsOutput != null) { fsOutput.Close(); }
}
}
This is the WinRT version that uses CryptographicEngine.
public static async Task EncryptContentFile(IRandomAccessStream inputStream, IRandomAccessStream outputStream, string key)
{
var iv = CryptographicBuffer.CreateFromByteArray(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 });
var keyMaterial = CryptographicBuffer.DecodeFromBase64String(key);
var cryptoProvider = SymmetricKeyAlgorithmProvider.OpenAlgorithm(SymmetricAlgorithmNames.DesCbcPkcs7);
var symmetricKey = cryptoProvider.CreateSymmetricKey(keyMaterial);
var inStream = inputStream.AsStreamForRead();
var outStream = outputStream.AsStreamForWrite();
try
{
var size = (long)inputStream.Size;
var chunkSize = 64L;
//var finalChunk = false;
while (inStream.Position < size)
{
if (size - inStream.Position < chunkSize)
{
chunkSize = size - inStream.Position;
//finalChunk = true;
}
var chunk = new byte[chunkSize];
await inStream.ReadAsync(chunk, 0, (int)chunkSize);
var writeBuffer = CryptographicEngine.Encrypt(symmetricKey, chunk.AsBuffer(), iv).ToArray();
await outStream.WriteAsync(writeBuffer, 0, (int)chunkSize);
//await outStream.WriteAsync(writeBuffer, 0, finalChunk ? writeBuffer.Length : (int)chunkSize);
}
await outputStream.FlushAsync();
}
catch (Exception e)
{
Debug.WriteLine(e.Message);
}
}
The goal is to be able to encrypt large files by reading and encrypting chunks of bytes. The problem that I have with the RT method is that everytime it encrypts a chunk, the encrypted bytes are larger by 8 bytes. I understand on the .NET side this is what CryptoStream.FlushFinalBlock() adds.
I tried trimming the bytes to the original size (the commented finalChunk code), but it didn't help.
How can I reliably encrypt in WinRT and have the final encrypted file be identical with what the .NET method produces.
Thank you
To answer my question, I found the problem. Windows Runtime doesn't support buffered encryption and will always treat data as a whole. While the .NET ICryptoTransform contains methods like TransformBlock and TransformFinalBlock, the RT API always uses treats data as final, which makes it impossible to encrypt large streams by chunks.
I ended up using BouncyCastle PCL library which worked out perfectly. Similarly, DesEngine in BouncyCastle has method ProcessBytes and DoFinal which correspond to the above mentioned .NET methods in ICryptoTransform.
Hope this helps someone.
private Task TransformStream_DesCbcPkcs7_WithProgress(bool forEncryption, Stream inputStream, Stream outputStream, byte[] key, byte[] iv, IProgress<int> progress)
{
return Task.Run(async () =>
{
// Initialize symmetric crypto engine
// Algorithm: DES
// Mode of operation: CBC
// Byte padding: PKCS#7
var engine = new PaddedBufferedBlockCipher(new CbcBlockCipher(new DesEngine()), new Pkcs7Padding());
engine.Init(forEncryption, new ParametersWithIV(new DesParameters(key), iv));
// Report progress if available
Action<int> report = x =>
{
if (progress != null)
progress.Report(x);
};
var size = inputStream.Length;
var current = inputStream.Position;
var chunkSize = 1024 * 1024L;
var lastChunk = false;
report(0);
await Task.Yield();
// Initialize DataReader and DataWriter for reliable reading and writing
// to a stream. Writing directly to a stream is unreliable.
using (var reader = new BinaryReader(inputStream))
using (var writer = new BinaryWriter(outputStream))
{
while (current < size)
{
if (size - current < chunkSize)
{
chunkSize = (uint)(size - current);
lastChunk = true;
}
var chunk = new byte[chunkSize];
reader.Read(chunk, 0, (int)chunkSize);
// The last chunk must call DoFinal() as it appends additional bytes
var processedBytes = lastChunk ? engine.DoFinal(chunk) : engine.ProcessBytes(chunk);
writer.Write(processedBytes);
current = inputStream.Position;
report((int)(current * 100F / size));
await Task.Yield();
}
await outputStream.FlushAsync();
}
});
}

Encrypting/Decrypting a file using C# and RSA

I am trying to encrypt and then decrypt an XML file using RSA and C# and while I'm really close, there's a problem. Once it's decrypted, almost all of the file is there but there's a hiccup toward the end. It's either a gap toward the end of the file or more data is appended to the very end of the file.
Here is my encrypt method:
public static bool Encrypt(ProcessingHolder ph)
{
FileInfo inFile = ph.encryptedFI;
FileInfo outFile = ph.unEncryptedFI;
X509Certificate2 daCert = new X509Certificate2(keyFP, daCertPassword);
RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)daCert.PrivateKey;
bool done = false;
FileStream fs = null;
FileStream fso = null;
try
{
//opens the file to encrypt into a filestream object
fs = inFile.OpenRead();
//240 is what the iOS side is using
//algorithm that calculates max bytes ((KeySize - 384) / 8) + 37
//(returns 245)
int chunkSize = 245;
fso = outFile.OpenWrite();
byte[] buffer = new byte[chunkSize];
int totalRead = 0;
while (totalRead < fs.Length)
{
int readBytes = fs.Read(buffer,0, chunkSize);
totalRead += readBytes;
//check to see if the final chunk of data is less than 245 so as not to write empty buffer
if (readBytes < chunkSize) buffer = new byte[readBytes];
//byte[] encr = new byte[readBytes];
//actual encryption
//encr = RSA.Encrypt(buffer, false);
byte[] encr = RSA.Encrypt(buffer, false);
fso.Write(encr, 0, encr.Length);
}
fso.Flush();
fso.Close();
fs.Close();
done = true;
}
catch (Exception ex)
{
Debug.WriteLine("Decrypt failed with message " + ex.Message);
done = false;
}
finally
{
if (fs != null) fs.Close();
if (fso != null) fso.Close();
}
return done;
}
}
and here is my decrypt method:
public static bool Decrypt(ProcessingHolder ph)
{
FileInfo inFile = ph.encryptedFI;
FileInfo outFile = ph.unEncryptedFI;
X509Certificate2 daCert = new X509Certificate2(keyFP, daCertPassword);
RSACryptoServiceProvider RSA = (RSACryptoServiceProvider)daCert.PrivateKey;
bool done = false;
FileStream fs = null;
FileStream fso = null;
try
{
fs = inFile.OpenRead();
int chunkSize = 256;
fso = outFile.OpenWrite();
byte[] buffer = new byte[chunkSize];
int totalRead = 0;
while (totalRead < fs.Length)
{
int readBytes = fs.Read(buffer, 0, chunkSize);
totalRead += readBytes;
//check to see if the final chunk of data is less than 245 so as not to write empty buffer
//if (readBytes < chunkSize) buffer = new byte[readBytes];
byte[] decr = RSA.Decrypt(buffer, false);
fso.Write(decr, 0, decr.Length);
}
fso.Flush();
fso.Close();
fs.Close();
done = true;
}
catch (Exception ex)
{
Debug.WriteLine("Decrypt failed with message " + ex.Message);
done = false;
}
finally
{
if (fs != null) fs.Close();
if (fso != null) fso.Close();
}
return done;
}
banging my head against the wall here, thanks in advance
What happens during encrypting if the file is not a multiple of the length of the chunk size? Ie. a file 500 bytes long would read two sets of 245, but they have 10 bytes left over? This might be loosing the last few bytes at the end or adding extra values?
Maybe you need to add a header to the file with the size in bytes of the decrypted file so that the decrypter knows where to stop and a way to pad out the final block during encryption

File Decryption Error: Bad Data

I am having some trouble getting a asp.net C# file encryption / decryption process to work. I can get the file uploaded and ecrypted, but cannot get the decryption to work.
I get the error: Exception Details: System.Security.Cryptography.CryptographicException: Bad Data. on the decryption line:
byte[] KeyDecrypted = rsa.Decrypt(KeyEncrypted, false);
Here is my encrypt function:
private void EncryptFile(string inFile)
{
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
ICryptoTransform transform = rjndl.CreateEncryptor();
byte[] keyEncrypted = rsa.Encrypt(rjndl.Key, false);
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
int lKey = keyEncrypted.Length;
LenK = BitConverter.GetBytes(lKey);
int lIV = rjndl.IV.Length;
LenIV = BitConverter.GetBytes(lIV);
int startFileName = inFile.LastIndexOf("\\") + 1;
// Change the file's extension to ".enc"
string outFile = EncrFolder + inFile.Substring(startFileName, inFile.LastIndexOf(".") - startFileName) + ".enc";
lblDecryptFileName.Text = outFile;
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
outFs.Write(LenK, 0, 4);
outFs.Write(LenIV, 0, 4);
outFs.Write(keyEncrypted, 0, lKey);
outFs.Write(rjndl.IV, 0, lIV);
using (CryptoStream outStreamEncrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write))
{
int count = 0;
int offset = 0;
int blockSizeBytes = rjndl.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
int bytesRead = 0;
using (FileStream inFs = new FileStream(inFile, FileMode.Open))
{
do
{
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamEncrypted.Write(data, 0, count);
bytesRead += blockSizeBytes;
}
while (count > 0);
inFs.Close();
}
outStreamEncrypted.FlushFinalBlock();
outStreamEncrypted.Close();
}
outFs.Close();
}
}
And here is the decrypt function where the error occurs.
private void DecryptFile(string inFile)
{
// Create instance of Rijndael for
// symetric decryption of the data.
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
string outFile = DecrFolder + inFile.Substring(0, inFile.LastIndexOf(".")) + ".txt";
using (FileStream inFs = new FileStream(EncrFolder + inFile, FileMode.Open))
{
inFs.Seek(0, SeekOrigin.Begin);
inFs.Seek(0, SeekOrigin.Begin);
inFs.Read(LenK, 0, 3);
inFs.Seek(4, SeekOrigin.Begin);
inFs.Read(LenIV, 0, 3);
int lenK = BitConverter.ToInt32(LenK, 0);
int lenIV = BitConverter.ToInt32(LenIV, 0);
int startC = lenK + lenIV + 8;
int lenC = (int)inFs.Length - startC;
// Create the byte arrays for
// the encrypted Rijndael key,
// the IV, and the cipher text.
byte[] KeyEncrypted = new byte[lenK];
byte[] IV = new byte[lenIV];
// Extract the key and IV
// starting from index 8
// after the length values.
inFs.Seek(8, SeekOrigin.Begin);
inFs.Read(KeyEncrypted, 0, lenK);
inFs.Seek(8 + lenK, SeekOrigin.Begin);
inFs.Read(IV, 0, lenIV);
Directory.CreateDirectory(DecrFolder);
byte[] KeyDecrypted = rsa.Decrypt(KeyEncrypted, false);
ICryptoTransform transform = rjndl.CreateDecryptor(KeyDecrypted, IV);
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
int count = 0;
int offset = 0;
int blockSizeBytes = rjndl.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
inFs.Seek(startC, SeekOrigin.Begin);
using (CryptoStream outStreamDecrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write))
{
do
{
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamDecrypted.Write(data, 0, count);
}
while (count > 0);
outStreamDecrypted.FlushFinalBlock();
outStreamDecrypted.Close();
}
outFs.Close();
}
inFs.Close();
}
}
Any help on this would be great! I am not an RSA encryption expert and have been reading a lot of posts but still not able to come up with a solution.
I have finally figured this out. The code worked well in a desktop application when I tried it there. It just didn't work in the asp.net 4 web application I was trying to write. The issue was the RSA object wasn't persisted through the session. So, the RSA object was created okay. The file was encrypted okay. But when I went to decrypt the file the RSA object was not there. The error message of System.Security.Cryptography.CryptographicException: Bad Data is misleading as that wasn't really the issue, the data was fine.
So, when creating the key and the RSA object I used the following:
rsa = new RSACryptoServiceProvider(cspp);
Session["rsa"] = rsa;
Next, when the decryption function is called I added in:
if (rsa == null)
rsa = (RSACryptoServiceProvider)Session["rsa"];
Of course, there is a little more code around this also so catch if there is no key for the RSA session, but this is the high level solution for the issue I was having.
If anyone is looking for this let me know and I can share more of the code.

.Net Task reporting progress?

I have a task that runs that uploads a byte array through a web service. I want to report the progress whenever it hits 10, 20, 30, 40 etc percent. In order to update that in the DB though, i need to pass a guid to the web service to identify the file reporting progress. I cannot reach that object from inside the task though. Any ideas?
Entry point:
Guid smGuid;
smGuid = Guid.NewGuid();
Task t1 = new Task(action, pubAttFullPath);
t1.Start();
string attFullFilePath = System.IO.Path.GetFullPath(
mailItem.Attachments[i].FileName);
string attExtension = System.IO.Path.GetExtension(
mailItem.Attachments[i].FileName);
pubAttFullPath = attFullFilePath;
pubAttFileName = mailItem.Attachments[i].FileName;
Task Code:
Action<object> action = (object obj) =>
{
//Set filename from object
string FileName;
FileName = System.IO.Path.GetFileName(obj.ToString());
//Declare Web Service
TransferFile.TransferFile ws_TransferFile = new TransferFile.TransferFile();
//
bool transfercompleted = false;
using (FileStream fs = new FileStream(
obj.ToString(),
FileMode.Open,
FileAccess.Read,
FileShare.Read))
{
//Declare Buffers and Counts
byte[] buffer = new byte[49152];
long fileSize = fs.Length;
long totalReadCount = 0;
int readCount;
int currentPacketNumber = 0;
int percentageComplete = 0;
//Loop and copy file until it changes to not exactly the same byte count as the buffer
//which means the file is about to complete.
while ((readCount = fs.Read(buffer, 0, buffer.Length)) > 0)
{
if (!transfercompleted)
{
totalReadCount += readCount;
byte[] bytesToTransfer;
if (readCount == buffer.Length)
{
//Copy bytes until buffer is different
bytesToTransfer = buffer;
ws_TransferFile.WriteBinaryFile(bytesToTransfer, FileName);
percentageComplete = (int)(totalReadCount / (double)fileSize * 100);
}
else
{
// Only a part is requred to upload,
// copy that part.
List<byte> b = new List<byte>(buffer);
bytesToTransfer = b.GetRange(0, readCount).ToArray();
ws_TransferFile.WriteBinaryFile(bytesToTransfer, FileName);
percentageComplete = 100;
transfercompleted = true;
fs.Close();
break;
}
}
}
}
};
How about just passing it in as a bound variable?
Guid smGuid;
smGuid = Guid.NewGuid();
Task t1 = new Task( _ => action( smGuid, pubAttFullPath ), null );
t1.Start();
Task code:
Action<Guid, string> action = (smGuid, FileName) =>
{
//Declare Web Service
TransferFile.TransferFile ws_TransferFile = new TransferFile.TransferFile();
//
bool transfercompleted = false;
// And so on...
}

Categories

Resources