-2

我想在文本框中异步显示内容?有人知道我下面列出的代码的错误吗?我想实现文本框中的文本将每秒更新为新值?我还想问为什么每次在调用控制器的调用方法之前都要检查 InvokeRequired ?

        private void Counting(int Num)
    {

        int i = 0;
        string counter = null;
        while (i < Num)
        {
            Thread.Sleep(1000);
            counter = string.Format(" {0}", i);
            tbxStatus.BeginInvoke(new UpdateStatusDelegate(UpdateStatus), new string[] { counter });
        }

    }

    public void UpdateStatus(string data)
    { 
        tbxStatus.Text += data;
    }

    public delegate void UpdateStatusDelegate(string data);

    public delegate void CountDelegate(int num);

    private void btnStart_Click(object sender, EventArgs e)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new CountDelegate(Counting), new object[] { 5 });
        }
        else
            Counting(5);
    }

谢谢

4

2 回答 2

1

我最近遇到了类似的问题。

我正在编写一个网络游戏,我想将文本附加到我拥有的文本框中,但是我会收到一条错误消息,说我试图从不同的线程更改 Windows 窗体控件,从而导致线程不安全。这是因为我在服务器端使用 ASyncCallback。

我以前有这个:(控制台方法是一个简单的方法,它获取一个字符串并将其附加到文本框)。

    console("message");

为了解决这个问题,我不得不把它改成这个,现在解决这个问题:

    this.Invoke((MethodInvoker)delegate { console("message"); });

希望这可以帮助遇到此问题的其他人。这可能不是最好的方法,但它对我有用。

问候。

于 2014-02-27T14:58:36.663 回答
1

您的InvokeRequired测试应该在委托内部:

public void UpdateStatus(string data)
{
    if (this.tbxStatus.InvokeRequired)
    {
        UpdateStatusDelegate d = new UpdateStatusDelegate(UpdateStatus);
        this.Invoke(d, new object[] { data });
    }
    else
    {
        this.tbxStatus.Text = data;
    }
}

如果您使用以下扩展方法,您还可以使这变得更容易和更清晰:

public static TResult SafeInvoke(this T isi, Func call) where T : ISynchronizeInvoke
{
    if (isi.InvokeRequired) {
        IAsyncResult result = isi.BeginInvoke(call, new object[] { isi });
        object endResult = isi.EndInvoke(result); return (TResult)endResult;
    }
    else
        return call(isi);
}

public static void SafeInvoke(this T isi, Action call) where T : ISynchronizeInvoke
{
    if (isi.InvokeRequired) isi.BeginInvoke(call, new object[] { isi });
    else
        call(isi);
}

因此,如果我想调用我在 UI 线程中定义的方法(例如在表单实例中定义的方法),您可以使用以下代码来执行此操作(无需创建任何委托或任何东西):

formInstance.SafeInvoke(f => f.myFormMethod("parameter1","parameter2"));

在您的情况下,您可以执行以下操作:

formInstance.SafeInvoke(f => f.UpdateStatus(myCounterInt.toString));

或类似的东西。

我已经在我的博客上写过关于使用它的文章,但是当我写这篇 CodeProject 文章时不要给我功劳

于 2012-07-27T03:58:22.460 回答