我一直试图做一些看似应该比我做的更容易的事情。
我想从一些工作线程更新程序GUI上的状态标签(I.E.进度)。
我无法使用同步调用调用,因为主线程在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();
}
非常感谢您提供的任何提示!
答案 0 :(得分:0)
修复你的方法,看起来更像是这样:
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线程。