Reputation: 15
I have this C# code, it works but it won't wait until the method completed
foreach (var listBoxItem in visualListBox1.Items)
{
lblCursor.Text = "Processing.. " + listBoxItem;
Thread t = new Thread(() => extract_group(listBoxItem.ToString()));
t.IsBackground = false;
t.Name = "Group Scrapper";
t.Start();
}
How to wait until extract_group
method is done before moving to the next listBoxItem
?
I used t.join()
but it made the UI unresponsive.
Upvotes: 0
Views: 1851
Reputation: 28948
If you want to stick with Thread I recommend using a WaitHandle e.g. AsyncManualResetEvent Class. This approach allows to make a thread wait without blocking CPU (e.g. spinlock). Your provided example would become:
private static AsyncManualResetEvent mre = new AsyncManualResetEvent(false, true);
public async Task DoSomethingAsync(...)
{
foreach (var listBoxItem in visualListBox1.Items)
{
lblCursor.Text = "Processing.. " + listBoxItem;
Thread t = new Thread(() => ExtractGroup(listBoxItem.ToString()));
t.IsBackground = false;
t.Name = "Group Scrapper";
t.Start();
// Wait for signal to proceed without blocking resources
await mre.WaitAsync();
}
}
private void ExtractGroup(string groupName)
{
// Do something ...
// Signal handle to release all waiting threads (makes them continue).
// Subsequent calls to Set() or WaitOne() won't show effects until Rest() was called
mre.Set();
// Reset handle to make future call of WaitOne() wait again.
mre.Reset();
}
Another solution would be to go with the TPL and use Task instead of Thread:
public async Task DoWorkAsync()
{
foreach (var listBoxItem in visualListBox1.Items)
{
lblCursor.Text = "Processing.. " + listBoxItem;
// Wait for signal to proceed without blocking resources
await Task.Run(() => ExtractGroup(listBoxItem.ToString()));
}
}
The issue with your code sample is, that you are currently on the main thread, the UI thread. Calling Thread.Join() does what you think it does: it blocks the waiting thread until the running thread completes. But as mentioned, the waiting thread is the UI thread, so the UI becomes unresponsive and can even deadlock in some scenario. When you use async/await your invocations become asynchronous and hence awaitable without blocking the UI thread.
Upvotes: 0
Reputation: 598
Using async/await helps you to not block main thread.
public async Task ExtractGroupAsync()
{
... (logic of the method)
... (you should use async methods here as well with await before executing those methods)
}
You execute this "ExtractGroup" task like:
var example = await ExtractGroupAsync();
Upvotes: 2
Reputation: 684
It makes GUI unresponsive, because you are on GUI thread. Run whole code, in separate thread. Note: when you want to access GUI elements from another thread, you should use invoke, for example:
t.Invoke(() => t.Name = "Group Scrapper");
Upvotes: 0