2012-04-13 62 views
1

我想在一个额外的线程中执行Heavy Process之后可以访问result(重进程的返回结果),因为它主要是期望在进程UI生效期间不需要, 过程完成后会与result从一个额外的线程返回结果

播放过程中某些搜索,并期待在我的文章中,我得到了有几种方法到 做到这一点,请提供你知道最好的方法或类似的情况下使用

这就是我要处理的最可能的方法的例子:

 public ACollection DoProcess(Document docProcess) 
     { 
      ACollection result = new ACollection(); 

      ThreadStart threadStart = delegate 
      { 
       result = MyProcess(docProcess); 
      }; 
      var threadProcess = new Thread(threadStart); 
      threadProcess.Start();  

      return result ; 
} 

其他可能的方法可能是IAsyncResult的,BackgroundWorker的,使用定时器和检查状态,而不是将结果返回到方法来处理它,它报告给UI直接在线程安全的方式给我们的UI控件发送...

请给你自己的意见和样品类似的情况下, 在此先感谢

编辑3:方法 - 基于Brian的回答

 LenzCollection myResultCollection = new LenzCollection();  

     TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext(); 

     Task.Factory.StartNew(() => 
      { 
       myResultCollection = DoCollect(docProcess); 
       //Task.WaitAll(); 

       return myResultCollection; 
      }).ContinueWith((task => 
      { 
       myResultCollection = task.Result; 
      }), ui); 

     return myResultCollection; 

它仍然没有等待,将不会得到预期的结果

+1

'while(threadProcess.IsAlive){}'使这个单线程。还有一个CPU-Hog。 – 2012-04-13 10:20:07

+0

我得到了几分钟后,编辑,谢谢,但仍需要知道你建议的可重复使用的方法,thr – LastBye 2012-04-13 10:22:06

+1

BackgroundWorker已经得到了所有你问到的功能。那么为什么要重新发明轮子? – Zarat 2012-04-13 10:26:47

回答

1

选项#1:

使用Task类和ContinueWith方法。

TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext(); 

Task.Factory.StartNew(() => 
    { 
    var result = MyProcess(docProcess); 
    return result.ToString(); 
    }).ContinueWith((task => 
    { 
    textBox1.Text = task.Result; 
    }, ui); 

您必须记住要将正确的同步上下文传入ContinueWith方法。你可以看到我如何用ui变量做到这一点。

选项#2:

使用新asyncawait关键字。

private async void SomeButton_Click(object sender, EventArgs args) 
{ 
    textBox1.Text = await Task.Run(() => 
    { 
     var result = MyProcess(docProcess); 
     return result.ToString(); 
    }); 
} 

显然,这是对眼睛更容易了很多,做了所有的编组和同步方面的东西给你。


新关键字将在C#5.0,但您可以通过Async CTP现在使用它们。 CTP使用TaskEx而不是Task

+0

这是另一个聪明的答案在这里,我喜欢它,如果它基于C#5.0现在可以适用,那么对我来说这没什么问题,现在可以适用,谢谢发布,我会在几分钟后回来,测试它,并会在需要时与您讨论,+1感谢您的参与ated inv :) – LastBye 2012-04-13 13:50:30

+0

我在发布之前测试了两种方法,因此它们应该可以工作。请记住,如果通过Async CTP使用第二种方法,则需要使用“TaskEx.Run”而不是“Task.Run”。这只是一个CTP的东西。 – 2012-04-13 14:15:41

+0

是的我看到了,我想适应自己和我的代码,并且需要时询问您:) – LastBye 2012-04-13 14:33:55

2

只实现一个事件,你你执行方法之前注册。让方法在完成时提升事件。

例如:

public delegate void MyEventHandler(string result); 
public class MyClass 
{ 
    public event MyEventHandler MyEvent; 
    private void Event(string result) 
    { 
    MyEventHandler handler = MyEvent; 
    if(handler != null) 
     handler(result); 
    } 

    public void DoSomethingLong() 
    { 
    //Do something 
    Event("Finish"); 
    } 
} 

现在你可以,如果你正在使用.NET Framework 4.0 or +用于调用到UI线程

void On_Event(string result) 
{ 
    if(this.InvokeRequired) 
    { 
    MyEventHandler handler = new MyEventHandler(On_Event); 
    Invoke(handler, new object[] { result }); 
    return; 
    } 
    // At this point you can access your UI without having Cross-Threaded operation! 
} 
+0

请在这种情况下提供一段代码 – LastBye 2012-04-13 10:28:13

+1

代码不够? – RaphaelH 2012-04-13 10:29:58

+0

我会检查它,并认为它可能是一段可重复使用的代码,因为一般事件,真的很感谢,它有什么缺点吗?你如何将它与BackgroundWorker进行比较? – LastBye 2012-04-13 10:38:00

1

运行此像

MyClass.Event += MyEventHandler(On_Event); 
Thread t = new Thread(MyClass.DoSomethingLong); 
t.Start();  

void On_Event(string result) 
{ 
    //Get executed when finished; 
} 

一个例子,你可以运行来自Task.ContinueWith中的另一个线程和进程的进程,例如

Process pro = null; 
Task.Factory.StartNew(() => { 
    pro =new Process(..); 
    pro.Start(); 
    pro.WaitForExit(); 
}).ContinueWith(..process data recieved from the pro) 

编辑

不要使用while(...),但使用pro.WaitForExit()

希望这有助于。

+0

这是这种情况下最好的方法?我对此并不熟悉,并认为它可能会有用,因为使用这个提供的代码可能在我的示例中使用? – LastBye 2012-04-13 10:30:48

+1

@Sypress:这是一个*最好*或不应该决定*你* :)这是*现代*方法和最紧凑的一个,在这种情况下。不需要声明事件,处理它们或定义BackgroundWorker。我建议你尝试一下(复制/粘贴),看看它是否符合你的需求。 – Tigran 2012-04-13 10:36:44

+0

我看,也许很傻,但它真的知道,我不能将我的代码带入/转换成它:D,如果“亲”是我上面提到的heavyProcess我的实例“结果”我知道它应该很简单你可以请你提供我的实例,并且让我能够更容易地根据它移动我的代码,非常感谢这种现代方法;) – LastBye 2012-04-13 10:43:32

2

在桌面(WinForms/WPF)应用程序中,最好和最简单的方法是BackgroundWorker。它旨在处理这个问题。

+0

在很多文章中,我看到它被推荐用于大多数类似的问题,但是你知道我想用我制作的模块的方式拥有更多的权限,这样我应该加入一些分离的代码并重塑模块/代码的结构,如果这是必要的,没有代码段可以挑战它,所以我会这样做,无论如何,将很高兴和赞赏,如果任何建议的代码示例,你可以给我的情况 – LastBye 2012-04-13 10:26:55