2014-01-14 43 views
-1

我有含有执行繁重的操作阻塞UI一个Run()方法的类。 我创建了类的几个实例,我需要执行run()同步W/O阻塞UI。 我已成功地做到用一个BackgroundWorker但是我不喜欢,因为这种解决方案“Application.DoEvents()”因为如果我需要等待后台工作完成,存在使用不使用BW。我应该使用同步操作。 任何想法我可以用呢?如何执行重同步操作W/O阻塞UI?

class MyClass 
{ 
    public void Run() 
    { 
     for (int i = 0; i < 1000; i++) 
     { 
      Console.WriteLine(i); 
     } 
    } 
} 


public partial class Form1 : Form 
{ 
    List<MyClass> lmc = new List<MyClass>(); 

    public Form1() 
    { 
     InitializeComponent(); 

     MyClass m1 = new MyClass(); 
     MyClass m2 = new MyClass(); 

     lmc.Add(m1); 
     lmc.Add(m2); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     foreach (MyClass item in lmc) 
     { 
      BackgroundWorker bw = new BackgroundWorker(); 
      bw.DoWork += bw_DoWork; 
      bw.WorkerSupportsCancellation = true; 
      bw.RunWorkerAsync(item); 
      while (bw.IsBusy) 
      { 
       Application.DoEvents(); 
      } 
     } 
    } 

    void bw_DoWork(object sender, DoWorkEventArgs e) 
    { 
     ((MyClass)e.Argument).Run(); 
     ((BackgroundWorker)sender).CancelAsync(); 
    } 
} 
+1

所以,基本上,你想一个解决方案,是不是异步任务,尽管这正是异步任务的情况? –

+1

您使用的是.NET Framework 4.5吗?如果是,请查看C#5中的新异步/等待关键字。 –

+0

这可能很有用http://msdn.microsoft.com/en-us/library/dd460717.aspx – Mike

回答

1

“DoEvents”确实不是一个好方法。 我建议使用TPL任务。

private void button1_Click(object sender, EventArgs e) 
{ 
    Task t = new Task(() => 
    { 
     lmc.ForEach(l => l.Run()); 
    }); 

    t.Start(); 

    t.ContinueWith(_ => 
    { 
     Invoke(new System.Action(UploadDone)); 
    }); 

} 

private void UploadDone() 
{ 
    Console.Write("Done"); 
} 

释放UI的唯一方法是释放主线程。你必须开始一个新的线程。

顺便说一句,如果LMC任务不互相转发,你也可以做Parallel Foreach

感谢,
阿米尔