2012-04-13 60 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