我想逐步创建一个新的线程,以编程方式创建浏览器选项卡并在该浏览器选项卡中执行事件。问题是我收到一条消息,说我无法对父线程中的UI对象执行UI影响。
所以我需要找到一种方法来告诉新线程使用主线程的UI对象。这应该很容易做对吗?
以下是我正在使用的代码片段:
//....to this point we have told the code to run selected items in a datagrid. Each will have it's own thread.
if (row.Cells[1].Value.ToString() == "True")
{
count_active++;
//begin multithreading
Thread this_thread = new Thread(() => f_play_campaign(row.Cells[0].Value.ToString(), row.Cells[2].Value.ToString()));
this_thread.Name = "thread_" + row.Cells[0].Value.ToString();
this_thread.IsBackGround = true;
this_thread.Start();
}
}
if (count_active == 0)
{
MessageBox.Show("No campaigns are selected!");
}
}
private void f_play_campaign(string project_id, string tab_name)
{
//MessageBox.Show(tab_name);
//add new tab
string browsername = f_create_new_tab(tab_name); //this is where the code breaks!
Control browser = f_get_control_by_name(browsername);
//MessageBox.Show(browser.ToString());
//... do more code
是否有一种简单的方法可以告诉线程使用主线程的UI对象?当我试图从我的方法f_create_new_tab()获取返回值时,我无法弄清楚如何使用Invoke(),而我在这方面是如此新,以至于我没有想出如何使用后台工作者和线程一样的方式。
我将继续阅读有关此问题的其他主题,但希望有人知道一个非常简单的优雅解决方案,可以满足像我这样的php程序员。
答案 0 :(得分:2)
几天前我不得不处理这个问题。这很容易解决:
Thread this_thread = new Thread(() =>
this.Invoke((MethodInvoker)delegate
{
f_play_campaign(row.Cells[0].Value.ToString(), row.Cells[2].Value.ToString();
}));
基本上,您需要传递Invoke
MethodInvoker
委托,该委托定义为public delegate void MethodInvoker()
。
如果您想使用BackgroundWorker
,那就非常相似:
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += (s, e) =>
{
this.Invoke((MethodInvoker) delegate { MyJobHere(); });
};
// Do the work
worker.RunWorkerAsync();
如果你想返回一些值,你可以这样做:
BackgroundWorker worker = new BackgroundWorker();
int value;
worker.DoWork += (s, e) =>
{
this.Invoke((MethodInvoker) delegate { value = DoSomething(); });
};
worker.RunWorkerAsync();
// do other processing
while (worker.IsBusy)
{
// Some other task
}
// Use the value
foo(value);
答案 1 :(得分:1)
添加新方法:
private void f_play_campaign_Async(string project_id, string tab_name)
{
Action<string, string> action = f_play_campaign;
this.Invoke(action, project_id, tab_name);
}
修改therad的构造以改为调用此方法:
Thread this_thread = new Thread(() => f_play_campaign_Async(row.Cells[0].Value.ToString(), row.Cells[2].Value.ToString()));