[英]c# Update label from sub-thread when using thread.join on the main thread
我坚持尝试做一些看起来比我做起来容易的事情。
我想从一些辅助线程更新程序GUI上的状态标签(即IE进度)。
我不能使用同步调用,因为主线程在thread.Join();上被阻塞了。 重新启用接口输入/清除线程。 这会导致程序冻结。
我不想使用异步BeginInvoke,因为它会等到程序完成更新进度为止……违背了目的。
tl; dr-我知道为什么它行不通,但是我不确定如何解决它。
Button_Search_Click(object sender, EventArgs e)()
{
DisableInput(); //Block input on start of function
Cursor.Current = Cursors.WaitCursor; //set wait cursor
//read combobox input
string objectType = comboBox_Object.SelectedItem.ToString();
string conditionType = comboBox_ConditionType.SelectedItem.ToString();
string conditionOperator = comboBox_equals.SelectedItem.ToString();
//create a list of worker threads
List<Thread> workerThreads = new List<Thread>();
//for each line in the textbox
foreach (string searchText in textBox_SearchText.Lines)
{
if (String.IsNullOrWhiteSpace(searchText)) continue;
//foreach line in a listbox
foreach (String uri in Get_selected_sites())
{
string cred = (creddict[uri]);
Thread thread = new Thread(() => Search(uri, cred, objectType, conditionType, conditionOperator, searchText));
workerThreads.Add(thread);
thread.Start(); //start main "work" function
}
// Wait for all the threads to finish
foreach (Thread thread in workerThreads)
{
thread.Join();
}
}
Displaydata();
EnableInput(); //unlock input
Cursor.Current = Cursors.Default; //set normal cursor
}
Search(uri, cred, objectType, conditionType, conditionOperator, searchText)
{
DoStuff();
//Update toolStripStatusLabel with progress stored in global int variable
//This doesn't work well because it waits until Thread.join() to update status label.
//BeginInvoke(new Action(() => Results_Count.Text = "Total Results = " + totalResults));
//This doesn't work at all because the main thread is blocked on Thread.Join() -- it freezes the program
//statusStrip1.Invoke(new Action(() => Results_Count.Text = "Total Results = " + totalResults));
//This doesn't work/errors/crashes because the GUI is being modified by a thread other than main
//Results_Count.Text = "Total Results = " + totalResults;
DoMoreStuff();
}
非常感谢您提供的任何提示!
修正您的方法,使其看起来像这样:
async void Button_Search_Click(object sender, EventArgs e)()
{
DisableInput(); //Block input on start of function
Cursor.Current = Cursors.WaitCursor; //set wait cursor
//read combobox input
string objectType = comboBox_Object.SelectedItem.ToString();
string conditionType = comboBox_ConditionType.SelectedItem.ToString();
string conditionOperator = comboBox_equals.SelectedItem.ToString();
//create a list of worker threads
List<Task> workerTasks = new List<Task>();
//for each line in the textbox
foreach (string searchText in textBox_SearchText.Lines)
{
if (String.IsNullOrWhiteSpace(searchText)) continue;
//foreach line in a listbox
foreach (String uri in Get_selected_sites())
{
string cred = (creddict[uri]);
workerTasks.Add(Task.Run(() => Search(uri, cred, objectType, conditionType, conditionOperator, searchText)));
}
await Task.WhenAll(workerTasks);
}
Displaydata();
EnableInput(); //unlock input
Cursor.Current = Cursors.Default; //set normal cursor
}
这样, Button_Search_Click()
不会在任务运行时阻止UI线程,并且您可以使用常规的Invoke()
或任何您喜欢的将更新发布到UI线程的机制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.