当前位置:  开发笔记 > 编程语言 > 正文

线程控制.Invoke

如何解决《线程控制.Invoke》经验,为你挑选了2个好方法。

我有一个功能

public void ShowAllFly()
{  
        cbFly.Items.Clear();
        cbFly.Items.Add("Uçu? Seçiniz...");

        dsFlyTableAdapters.tblFlyTableAdapter _t=new KTHY.dsFlyTableAdapters.tblFlyTableAdapter();
        dsFly _mds = new dsFly();
        _mds.EnforceConstraints = false;
        dsFly.tblFlyDataTable _m = _mds.tblFly;
        _t.Fill(_m);
        foreach (DataRow _row in _m.Rows)
        {
            cbFly.Items.Add(_row["FlyID"].ToString()+"-"+_row["FlyName"].ToString() + "-" + _row["FlyDirection"].ToString() + "-" + _row["FlyDateTime"].ToString());
        }
        _Thread.Abort();
        timer1.Enabled = false;
        WaitPanel.Visible = false;
}

在Form_Load函数中像这样;

{
    _Thread = new System.Threading.Thread(new System.Threading.ThreadStart(ShowAllFly));
    _Thread.Start();
    _Thread.Priority = System.Threading.ThreadPriority.Normal;
}

但是当我跑的时候;

在ShowAllFly函数中

cbFly.Items.Clear(); ----  HERE Gives ERROR  LIKE  Control.Invoke must be used to interact with controls created on a separate thread.

问题是什么?



1> Jon Skeet..:

Windows窗体中有两个主要的线程规则:

除了创建控件的"句柄"之外的任何线程(通常只有一个UI线程),不要触摸任何控件属性或方法(除了明确列出的那些没有)

不要在任何相当长的时间内阻止UI线程,否则您将使应用程序无响应

为了从不同的线程与UI进行交互,您需要使用委托并调用Control.Invoke/ 来"调整"对UI线程的调用BeginInvoke.你可以测试你是否需要Invoke使用该InvokeRequired属性进行调用,但是这些天我个人倾向于只是这样做 - 当你不需要时调用没有太多的惩罚.

C#3中的Lambda表达式(或C#2中的匿名方法)也使这更令人愉快.

例如,您可以使用:

cbFly.Invoke((MethodInvoker)(() => cbFly.Items.Clear()));

所有括号都会受到影响,所以如果你使用C#3,你可能想要添加这样的扩展方法:

public static void Invoke(this Control control, MethodInvoker action)
{
    control.Invoke(action);
}

然后你可以这样做:

cbFly.Invoke(() => cbFly.Items.Clear());

这简单易行.通常,您可以MethodInvoker通过捕获代理中需要访问的任何变量来逃避使用.

有关详细信息,请参阅我的线程教程或Joe Albahari's.

作为次要问题,我看到你正在使用Thread.Abort- 实际上是在你自己的线程上,尽管它之后还有其他的调用.为什么?中止任何线程其他比你自己是一个"只有紧急"呼叫类型(这通常应遵循由应用正在反正卸载),我看不出有任何理由中止当前线程时,有仍有许多工作之后进行. ..



2> Ralf de Klei..:

需要调用另一个(ui)线程中控件的交互,如下所示:

public delegate void ProcessResultDelegate(string result);
void ProcessResult(string result)
{
    if (textBox1.InvokeRequired)
    {
        var d = new ProcessResultDelegate(ProcessResult);
        d.Invoke(result);
    }
    else
    {
        textBox1.Text = result;
    }
}


好的解决方案 byt我建议使用框架中的`Action `而不是滚动(和维护)你自己的.
推荐阅读
郑小蒜9299_941611_G
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有