Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 线程控制。调用_C#_Multithreading - Fatal编程技术网

C# 线程控制。调用

C# 线程控制。调用,c#,multithreading,C#,Multithreading,我有一个函数 public void ShowAllFly() { cbFly.Items.Clear(); cbFly.Items.Add("Uçuş Seçiniz..."); dsFlyTableAdapters.tblFlyTableAdapter _t=new KTHY.dsFlyTableAdapters.tblFlyTableAdapter(); dsFly _mds = new dsFly();

我有一个函数

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;
}
以这样的形式加载函数

{
    _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.

问题是什么?

在另一个(ui)线程中对控件的交互需要这样调用:


Windows窗体中的线程有两条黄金法则:

  • 除了创建控件“句柄”的线程(通常只有一个UI线程)之外,不要从任何线程中接触任何控件属性或方法(明确列出为OK的线程除外)
  • 不要长时间阻塞UI线程,否则会使应用程序无响应
为了从不同的线程与UI交互,您需要使用委托和调用
Control.Invoke
/
BeginInvoke
来“整理”对UI线程的调用。您可以使用
invokererequired
属性来测试是否需要调用
Invoke
,但现在我个人倾向于这样做——当您不需要调用时,调用不会有太大的惩罚

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

例如,您可以使用:

cbFly.Invoke((MethodInvoker)(() => cbFly.Items.Clear()));
所有的括号都有点妨碍,所以如果您使用的是C#3,您可能需要添加这样的扩展方法:

然后你可以做:

cbFly.Invoke(() => cbFly.Items.Clear());
这要简单得多。通常,您可以使用
MethodInvoker
捕获需要在委托中访问的任何变量

有关更多详细信息,请参阅或

其次,我看到您正在使用
Thread.Abort
——实际上是在您自己的线程上,尽管后面还有其他调用。为什么?中止除您自己的线程以外的任何线程都是一种“仅限紧急情况”类型的调用(通常在卸载应用程序之后),我看不出有任何理由在以后还有工作要做时中止当前线程…

我一直觉得在这个特定问题上有帮助

在您的示例中,您试图从未创建控件的线程修改各种控件。若要在示例中解决此问题,请改为这样做(假设ShowAllFly()方法是表单上的一个方法):


为了强调@Jon Skeet的观点,我已经注释掉了中止线程的调用。这根线将自动结束。没有理由以这种方式中止它。

它必须被调用。。。但调用必须等待主线程,我的意思是,您不会以这种方式得到错误,但这不是并行工作,如果您想同时执行多个进程,只需创建多个线程

Thread thread = new Thread(new delegate_method(method));//you must create delegate before
thread.start ();
Thread thread2 = new Thread(new delegate_method(method2));//you must create delegate before
thread.start ();
同时处理两个进程

    void method ()
{
//do something here -- working background Remember can not control any UI control from here
finish_thread()
}

void method2 ()
{
//do something here -- working background Remember can not control any UI control from here
finish_thread()
}

void finish_thread()
{
if(invoke.Required)
{
//Here you have to call delegate method here with UI
BeginInvoke(new delegate_method(finish_thread));
}
else
{
//Now you can control UI thread from here and also you finished background work
//Do something working with UI thread
textBox.Text = "";
}
}

这是线程中控件工作的最佳方式

首先,您必须从单线程单元线程使用

...
Thread th = new Thread(yourThreadStart);
            th.SetApartmentState(ApartmentState.STA);
th.Start();
...
接下来在代码之间复制此方法

public static void SetControlThreadSafe(Control control, Action<object[]> action, object[] args)
{
      if (control.InvokeRequired)
            try { control.Invoke(new Action<Control, Action<object[]>, object[]>(SetControlThreadSafe), control, action, args); } catch { }
      else action(args);
}

享受…

好的解决方案;byt我建议使用框架中的
操作
,而不是滚动(和维护)自己的。是的。。这几乎是做这件事的标准方法。之所以需要这样做,是因为textBox1.Text只能在创建textbox的线程上更改-调用是用于返回该线程的过程。@Fredrik:没错,但这个例子更常见,很大程度上是因为它存在的时间更长。因为他是最好的,我给了他一票,在我之前没有人给过(暗示,暗示)。
    void method ()
{
//do something here -- working background Remember can not control any UI control from here
finish_thread()
}

void method2 ()
{
//do something here -- working background Remember can not control any UI control from here
finish_thread()
}

void finish_thread()
{
if(invoke.Required)
{
//Here you have to call delegate method here with UI
BeginInvoke(new delegate_method(finish_thread));
}
else
{
//Now you can control UI thread from here and also you finished background work
//Do something working with UI thread
textBox.Text = "";
}
}
...
Thread th = new Thread(yourThreadStart);
            th.SetApartmentState(ApartmentState.STA);
th.Start();
...
public static void SetControlThreadSafe(Control control, Action<object[]> action, object[] args)
{
      if (control.InvokeRequired)
            try { control.Invoke(new Action<Control, Action<object[]>, object[]>(SetControlThreadSafe), control, action, args); } catch { }
      else action(args);
}
...

    SetControlThreadSafe(textbox1, (arg) =>
          {
                textbox1.Text = "I`m Working in a Thread";
          }, null);
...