.net框架下的并行任务

本文关键字:并行任务 框架 net | 更新日期: 2023-09-27 18:02:26

我正在研究并行性,想知道你推荐我访问其他头部元素的方式,例如imagima,我会用一些名字填充一个组合框,查询数据库,我会并行做,但我不能做一个组合框。从任务中添加(结果),你推荐我用哪种方法?

一个简单的例子来理解我的问题:

 private void button1_Click (object sender, EventArgs e)
         {
             Task task = new Task (new Action (Count));
             task.Start ();
         }

         void Count ()
         {
             for (int i = 0; i <99; i + +)
             {
                 Thread.Sleep (1);
                 progressBar1.Value = i;
             }
         }

传递进度条值的时间导致错误

.net框架下的并行任务

如果要调度访问UI控件的任务,则需要将当前同步上下文传递给调度程序。如果您这样做,调度程序将确保您的任务在正确的线程上执行。例如

var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() => {
    // code that access UI controls
}, uiScheduler);

更多信息请参见http://msdn.microsoft.com/en-us/library/dd997402.aspx

您不能直接访问另一个线程上的控件。您必须首先调用它们。阅读本文:http://msdn.microsoft.com/en-us/library/ms171728.aspx

这是关于如果你把这篇文章翻译成你自己使用的样子:(未测试)

        delegate void SetProgressBarCallback();
        private void SetProgressBar()
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.progressBar1.InvokeRequired)
            {   
                SetProgressBarCallback d = new SettProgressBarCallback(SetProgressBar);
                this.Invoke(d);         
            }
            else
            {
                for(int i=0; i<99; i++)
                {
                     Thread.Sleep(1);
                     progressBar1.Value = i;
                 }
            }
        }

只是一个快速提示…WinForms中的UI只能从UI线程更新。也许你应该考虑使用Control.Invoke来更新你的progressBar1

Ryan的答案是正确的,但是他把sleep放在了调用中,这导致程序挂起。下面是一个示例,使用了他所做的相同的事情,但它没有在调用中放置sleep。

     private void button1_Click (object sender, EventArgs e)
     {
         Task task = new Task (new Action (Count));
         task.Start ();
     }

     void Count ()
     {
         for (int i = 0; i <99; i + +)
         {
             Thread.Sleep (1);
             if(progressBar1.InvokeRequired)
             {
                  int j = i; //This is required to capture the variable, if you do not do this
                             // the delegate may not have the correct value when you run it;
                  progressBar1.Invoke(new Action(() => progressBar1.Value = j));
             }
             else
             {
                 progressBar1.Value = i;
             }
         }
     }

必须执行int j = i来捕获变量,否则可能会在循环中显示i的错误值。