C#中委托语法的问题

6
我建立了一个测试盒来学习Windows窗体应用程序中的线程相关知识。Silverlight和Java都提供了Dispatcher,它在更新GUI元素时非常有帮助。
代码示例: 声明类委托
public delegate void d_SingleString(string newText);

创建线程
        _thread_active = true;
        Thread myThread = new Thread(delegate() { BackGroundThread(); });
        myThread.Start();

线程函数

    private void BackGroundThread()
    {
        while (_thread_active)
        {
            MyCounter++;
            UpdateTestBox(MyCounter.ToString());
            Thread.Sleep(1000);
        }
    }

委托文本框更新

    public void UpdateTestBox(string newText)
    {
        if (InvokeRequired)
        {
            BeginInvoke(new d_SingleString(UpdateTestBox), new object[] { newText });
            return;
        }
        tb_output.Text = newText;
    }

有没有一种方法可以在BeginInvoke方法中声明Delate的声明?!

类似于:

BeginInvoke(*DELEGATE DECLARATION HERE*, new object[] { newText });

非常感谢,rAyt。
2个回答

9
在许多这样的情况下,最简单的方法是使用“捕获变量”在线程之间传递状态;这意味着您可以将逻辑局部化:
public void UpdateTestBox(string newText)
{
    BeginInvoke((MethodInvoker) delegate {
        tb_output.Text = newText;
    });        
}

如果我们期望它在工作线程上被调用(因此没有检查InvokeRequired的必要),则上述方法特别有用 - 请注意,这对于UI线程或工作线程都是安全的,并允许我们在线程之间传递尽可能多或尽可能少的状态。


喜欢你的详细解释,Marc。比起阅读 MSDN 十分钟,我学到了更多 :) - Henrik P. Hessel
1
@Spence - 这与STA/MTA完全无关。 - Marc Gravell
没问题,我们都是回复狂热者,但也必须谦虚地推广更好的解决方案 ;) - Fredrik Mörk
你必须在UI线程上调用才能执行更新,这与Winforms是STA线程库无关吗? - Spence
@Spence - 正确。这与MTA/STA无关,而与“线程亲和性”有关,这是一个正交(尽管相关)的概念。 - Marc Gravell
显示剩余2条评论

4

对于像这样的简单委托,您可以使用框架中的Action<T>委托(链接到 msdn)。

public void UpdateTestBox(string newText)
{
    if (InvokeRequired)
    {
        BeginInvoke(new Action<string>(UpdateTestBox), new object[] { newText });
        return;
    }
    tb_output.Text = newText;
}

那样你就不需要维护自己的委托声明。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接