Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.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#_Winforms_Multithreading_Label - Fatal编程技术网

C#如何处理线程切换?

C#如何处理线程切换?,c#,winforms,multithreading,label,C#,Winforms,Multithreading,Label,我正在开发一个应用程序,其中两个线程同时从一个类执行一个方法。此方法执行一些复杂的计算,结果显示在WinForm中 所以我的班级看起来像: class Comp_func { /* Constructor */ public Comp_func() { } public void THE_Complex_func(string One, Int16 Two, Int32 Three) { Calculate_this(One);

我正在开发一个应用程序,其中两个线程同时从一个类执行一个方法。此方法执行一些复杂的计算,结果显示在WinForm中

所以我的班级看起来像:

class Comp_func
{
    /* Constructor */
    public Comp_func()
    {
    }

    public void THE_Complex_func(string One, Int16 Two, Int32 Three)
    {
        Calculate_this(One);
        Thread.Sleep(10);
        Calculate_that(Two);
        Thread.Sleep(10);
        Calculate_thatThat(Three);
        Thread.Sleep(10);
        Update_lable_in_form(value);
        Thread.Sleep(10);
    }
}
每个线程在WinForm中更新不同的
标签
,因此,我认为线程同步不会出现问题(因为我使用了线程安全方法)

我需要的是这些更新应该同时发生(至少看起来是同时发生的)

当用户单击我表单中的“计算”按钮时,我执行以下操作:

Comp_func Func1_class = new Comp_func();
Comp_func Func2_class = new Comp_func();

Thread Func1_Thread = new Thread(() => Func1_class.Start_Test("Blah", 2,3));
Thread Func2_Thread = new Thread(() => Func2_class.Start_Test("BlahBlah", 4,5));

//Func1_Thread.Priority = ThreadPriority.Highest;  /* Deleted after Comments */
   // Func2_Thread.Priority = ThreadPriority.Highest;  /* Deleted after Comments */


Func1_Thread.Start();
Func2_Thread.Start();

/*
  //  Removed after Comments 

// Let only Threads Run
 while(true)
{
    Application.DoEvent();
    Update();
}

for(count = 0; count < 100; count++)
 {  
    console.WriteLine("I WON'T USE WHILE(1) loops with DOEVENTS");
 }

*/
Comp_func Func1_class=new Comp_func();
Comp_func Func2_class=新Comp_func();
线程Func1_Thread=新线程(()=>Func1_class.Start_Test(“Blah”,2,3));
线程Func2_Thread=新线程(()=>Func2_类.Start_测试(“BlahBlah”,4,5));
//Func1_Thread.Priority=ThreadPriority.Highest;/*评论后删除*/
//Func2_Thread.Priority=ThreadPriority.Highest;/*评论后删除*/
Func1_Thread.Start();
Func2_Thread.Start();
/*
//评论后删除
//只让线程运行
while(true)
{
Application.DoEvent();
更新();
}
用于(计数=0;计数<100;计数++)
{  
WriteLine(“我不会使用WHILE(1)与DOEVENTS循环”);
}
*/
我的问题是,当线程1的执行完成时,它会更新
标签
,然后线程2启动并执行

为了避免这种行为,我编写了
Thread.Sleep()几乎在每行之后。它的行为仍然像windows不负责切换一样

知道为什么会这样吗


提前谢谢

您的代码示例非常不完整-因此很难看到发生了什么

我要说的第一点是,您不应该在单击处理程序中有一个无限循环-事实上,您根本不应该需要
while(true)…DoEvent()
代码

为了响应您要求两个标签同时更新的要求,最好的做法是在更新UI之前让线程连接起来-其中一种方法是创建一个BackgroundWorker来启动其他两个线程,join()s,然后用两个结果更新UI-根据您正在运行的.net版本,您可以使用任务库以较少的代码完成此操作

下面是一个相当粗糙的实现(如果您没有可用的任务库):

摆脱sleep()调用和DoEvents()循环,正如@dice所建议的那样——不管你怎么想,它们都没有帮助。如果您正确地调用/开始调用标签更改,您应该不会有问题-只需退出OnClick事件处理程序。您不应该在GUI事件处理程序中等待

重复-不要尝试在GUI事件处理程序中等待

您有多少个处理器内核,为什么要提高工作线程的优先级?如果您只有一个CPU,并且在Func1_线程上启动了CPU密集型任务,那么它将使用100%的CPU运行,直到它自身停止,或者Windows反饥饿算法在30秒后给其他线程几个周期。这会给人一种序列化的印象


将线程提高到高优先级,然后插入sleep()调用只是。。。好吧,别这样

关于线程,有些东西你真的不明白

您无法确定操作系统将如何处理线程的执行。 如果你想同时更改标签,你必须自己做

例如,在超级函数结束时引发一个事件,例如,让我们将其称为SuperCalcDone。
在SuperCalcDone处理程序上,只需检查所有计算是否完成,然后更新标签。

您希望发生什么?关于一些通常被认为是坏习惯的事情的旁注;显式声明线程优先级,无限循环。为什么需要线程。睡眠线?我的问题是线程切换不正确。执行类似于线程1完成,然后线程2完成。所以我想线程。睡眠会迫使线程切换。你怎么知道线程没有切换?通过函数调用,在每个线程中只更新UI一次—当每个线程完成其工作时。对于你的代码,线程1总是在线程2之前完成。如果你接受了dice和Martin James所说的一切,你的程序应该做你想做的事情。简单多线程(如果这本身不是矛盾的话)的一个指导原则是避免显式定义行为。编写线程类的人比大多数开发人员更了解它。所以,不要改变优先顺序,也不要强迫睡眠,除非你真的知道他们为什么会这样required@dice我希望UI中的两个标签应该同时更新。。。这意味着他们应该在几乎同一时间更新,但它就像标签I更新,然后说1秒后,标签II更新!怎么做?我在那里放了一些“OutputDebugString”,还显示了线程1的调试字符串,然后是线程2的调试字符串。这是我编写的测试代码,目的是向你们解释这个条件。我想处理一些计时器函数,并通过线程更新表单,所以我编写了DoEvent()和Update():(“处理一些计时器函数”-Windows.Forms.Timers只要退出OnClick处理程序就可以了。“通过线程更新表单”(使用Invoke/BeginInvoke),如果您退出OnClick处理程序,将正常工作。感谢您的建议…我会记住这一点!但我插入了线程。睡眠用于切换…我认为睡眠一个线程将唤醒另一个线程…优先级是一个试验…我在双核3GHz机器上运行!感谢您的建议,但我希望它应该继续更新…并且他的例子是,在实际代码中,我几乎需要在每个函数之后更新标签。还有14个这样的函数。:(两个线程正在处理独立的数据!
    private void button1_Click(object sender, System.EventArgs e)
    {
        BackgroundWorker master= new BackgroundWorker();
        master.DoWork += (sender1, e1) =>
                              {
                                  Thread t1 = new Thread(Func1_class.Start_Test);
                                  Thread t2 = new Thread(Func1_class.Start_Test);
                                  t1.Start();
                                  t2.Start();
                                  t1.Join();
                                  t2.Join();
                              };
        master.RunWorkerCompleted += (sender2, e2) =>
                                          {
                                              label1.Text = "text";
                                              label2.Text = "text";
                                          };
        master.RunWorkerAsync();
    }