Reputation: 13296
i have file transfer application (Server-Client) TCP [.net 4] why is backgroundworker gives me an exception in (backgroundWorker1_ProgressChanged)
The client send command that has a destination path (where file should saved into) and the size of file to the Server to start receiving that file .. so once the server takes that command .. it will call :
fileTransfer1.Receive(destPath, fileSize);
this method run in its own thread in form1.cs :
private void Job(object o)
{
Socket client = (Socket)o;
NetworkStream stream = new NetworkStream(client);
StreamReader sr = new StreamReader(stream);
string cmd = null;
while ((cmd = sr.ReadLine()) != null)
{
string[] command = cmd.Split('<');
switch (command[0])
{
case "receive":
fileTransfer1.Receive(command[1], Convert.ToInt64(command[2]));
break;
default:
break;
}
}
fileTransfer1 (userControl) :
public void Receive(string destPath, long fileSize)
{
List<object> job = new List<object>();
job.Add(destPath);
job.Add(fileSize);
backgroundWorker1.RunWorkerAsync(job);
}
long sum = 0;
long fileSize = 0; //this will equal the size of the file later.
private void ReceiveFile(string destPath, long fileSize)
{
using (fs = new FileStream(destPath, FileMode.Create, FileAccess.Write))
{
try
{
int count = 0;
data = new byte[packetSize];
while (sum < fileSize)
{
count = network.Read(data, 0, packetSize);
fs.Write(data, 0, count);
sum += count;
backgroundWorker1.ReportProgress((int)((sum * 100) / fileSize));
}
}
finally
{
CloseTransfer();
}
}
}
here's backgroundworker method :
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
List<object> job = (List<object>)e.Argument;
string destPath = (string)job[1];
long fileSize = (long)job[2];
ReceiveFile(destPath, fileSize);
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBarFile.Position = e.ProgressPercentage;
progressBarFile.Text = progressBarFile.Position.ToString() + "%";
/*here*/ labelRemaining.Text = CnvrtUnit(fileSize - sum);
}
my problem that i got an exception (Cross-thread operation not valid: Control 'labelRemaining' accessed from a thread other than the thread it was created on.) that references to this line:
labelRemaining.Text = CnvrtUnit(fileSize - sum);
i know about that exception and i know that i have to use (delegate/invoke) thing .. but.. i know that backgroundworker meant for this .. plus .. i have the same code but The server here Send a file to the client .. and it doesn't give that exception .. it works fine and the form shows me the details as it should be.
So why do i get this exception just when i receive a file ??
note : receive method works fine.
Upvotes: 0
Views: 3156
Reputation: 13296
i've figured that out
since my command receiver method Void Job(object o) is running under a thread .. so this:
case "receive":
fileTransfer1.Receive(command[1], Convert.ToInt64(command[2]));
break;
also runs in the same thread .. that means the rest of the code also runs in that thread .. so i just changed this line to this:
case "receive":
Action a = () => fileTransfer1.Receive(command[2], Convert.ToInt64(command[3]));
Invoke(a);
break;
now UI-Thread will be notified to run the rest of the receiving code .. which solved my problem.
Upvotes: 0
Reputation: 5799
You are getting that error because backgroundWorker1_ProgressChanged()
is running on a thread different from the thread that created the labelRemaining
control. Assuming you created the labelRemaining
control on the main UI thread, you need to either:
Execute backgroundWorker1.RunWorkerAsync(job)
from the main thread.
or
Inside backgroundWorker1_ProgressChanged
, use the Dispatcher to execute the change to your labelRemaining
object on the main thread as described here
Update: I see you are using winforms and not WPF. Rather than using the Dispatcher this should work for you: How to update the GUI from another thread in C#?
Upvotes: 2