从新线程调用/修改UI

本文关键字:调用 修改 UI 线程 新线程 | 更新日期: 2023-09-27 18:15:38

我想以编程方式创建一个新的线程,以编程方式创建一个浏览器选项卡,并在该浏览器选项卡内执行事件。问题是我得到一条消息说我不能在父线程的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程序员。

从新线程调用/修改UI

几天前我不得不处理这个问题。这很容易解决:

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);

添加新方法:

    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);
    }

修改线程的构造,改为调用此方法:

Thread this_thread = new Thread(() => f_play_campaign_Async(row.Cells[0].Value.ToString(), row.Cells[2].Value.ToString()));