Reputation: 580
Background
Currently working on a windows form app which I asked to create. I have ran into an issue where the UI freezes when a resource intensive process is being called. I am currently using threading from which I understand is used to prevent the UI from freezing and taking over the entire pc.
Question
Currently when I am using threading to call a method in my base class which is to open a file that is located on a remote server. This method has a delay of approximately 30 to 45 seconds. I am creating my background thread and invoking it to start. When invoked to start if fires, however when it fired it would not wait for my thread to complete basically giving me a null exception. So after some digging I found that in order to wait for the thread to complete you had to invoke the .Join()
. However when the Join is invoked it froze my UI completely. So my ingenuity tried to create a work around and created a while loop that would until the thread is no longer alive and continue. However, this also froze the UI. So am I missing something? That is not mention in MSDN Doc
Code Sample
class BaseClass
{
public CWClient ClientFileContext(string clientFile, bool compress)
{
Client clientContext = null;
try
{
if (compress == true)
{
clientContext = appInstance.Clients.Open2(clientFile, superUser, passWord, OpenFlags.ofCompressed);
}
else
{
clientContext = appInstance.Clients.Open2(clientFile, superUser, passWord, OpenFlags.ofNone);
}
}
catch (Exception ex)
{
//TODO
}
return clientContext;
}
}
public partial class Form1 : Form
{
private void button1_Click(object sender, EventArgs e)
{
BaseClass wpSec = new BaseClass();
CWClient client = null;
Thread backgroundThread = new Thread(
new ThreadStart(() =>
{
client = wpSec.ClientFileContext(selectedFileFullPath, true);
}
));
backgroundThread.Start();
//backgroundThread.Join(); << Freezes the UI
var whyAreYouNotWorking = "Stop";
}
}
Work around I tried
while (backgroundThread.IsAlive == true)
{
for (int n = 0; n < 100; n++)
{
Thread.Sleep(500);
progressBar1.BeginInvoke(new Action(() => progressBar1.Value = n));
}
}
// This also freezes the UI
Upvotes: 1
Views: 2567
Reputation: 7010
I would also look into the async
and await
pattern for this. Explained in this post: Using async await still freezes GUI
Your code should be similar to this (Baseclass doesn't change) :
public partial class Form1 : Form
{
private async void button1_Click(object sender, EventArgs e)
{
BaseClass wpSec = new BaseClass();
CWClient client = await Task.Run(() =>
{
return wpSec.ClientFileContext(selectedFileFullPath, true);
}
);
var whyAreYouNotWorking = "Stop";
}
}
This is back-of-the-envelope stuff, but hopefully that gives the basic idea of launching a task, then awaiting the result in an async
method. If you don't need your BaseClass hanging around, that can be in the lambda too, leaving you only what you really want.
That link from @Chris Dunaway above is also excellent. http://blog.stephencleary.com/2013/08/taskrun-vs-backgroundworker-round-3.html
Edit: As @BradlyUffner mentions, this is also one of the few times you should use async void
and should rather prefer returning Task
or Task<T>
in virtually all other circumstances.
Upvotes: 3