2011-07-25 35 views
0

背景:我曾在表單加載期間調用存儲過程。然而,由於這導致了不太理想的用戶體驗,我把自己的SP調用放入了一個自己的任務中,在Shown事件中。由於這通常是表單顯示過程中的最後一個事件,因此與將事件放入表單加載事件相比,它產生了更好的體驗。我有:如何在非GUI線程中獲得任務完成通知

private void MainForm_Shown(object sender, EventArgs e) 
{ 
    dbCheckTask = Task<bool>.Factory.StartNew(RunSPAndCheckStuff()); 

    // both of below run on the GUI thread. 

    // if I print the thread ID in mycallback it is the GUI thread id 
    dbCheckTask.ContinueWith(mycallback()); 

    // I also tried below. But obviously, that too runs on the GUI thread 
    mycallback(dbCheckTask.Result) 

} 

因爲他們開火的GUI線程上,我的啓動窗體油漆還沒有瞬時也不順利。如何在不使用事件的情況下在非GUI線程上完成我的任務完成回調?每當任務完成時,如果出現錯誤,並且只有出現錯誤(布爾結果返回false),用戶纔會彈出消息框。在此之前,他可以繼續在表單上完成其他與數據庫無關的內容。請告知我如何在非GUI線程中獲得任務完成回調並顯示任務結果。謝謝

+0

這看起來對我來說,它應該已經工作 - 你可以張貼代碼或僞代碼爲myCallBack函數()方法? – Stuart

+0

我相信你可以使用TaskScheduler.Default來獲得一個沒有綁定到同步上下文的調度器。事實上,您看到此問題意味着TaskScheduler.Current在某個時刻被設置爲一個sycnchronized任務調度程序。 –

+0

@Stuart。如果其他人對此問題的建議不起作用,將會發布一些示例代碼。thx – Gullu

回答

1

我個人使用BackgroundWorker。一個辦法讓你的回調任務線程上運行,將修改您的方法調用和任務的創建如下:

private void MainForm_Shown(object sender, EventArgs e) 
{ 
    dbCheckTask = Task<bool>.Factory.StartNew(() => RunSPAndCheckStuff(mycallback)); 
    ... 
} 

private bool RunSPAndCheckStuff(Action<bool> callback) 
{ 
    bool result = false; 
    // Do stuff 
    callback(result); 
    return result; 
} 
+0

我認爲這將工作。將嘗試併發回thx – Gullu

+0

thx先生。作品。 – Gullu

+0

雖然這確實起作用,後臺線程將被阻止,等待SP返回。每當處理任何類型的I/O時,都應該使用適當的異步API。 – BFree

1

你應該考慮使用異步API的,而不是調用同步版本在後臺線程:

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.beginexecutenonquery.aspx

到的優點是沒有線程將被阻止,我相信回調將在ThreadPool線程上調用,例如不在GUI線程上。從那裏你可以用Invoke/BeginInvoke將任何GUI調用封送回GUI線程。

+0

從來沒有想過這樣做。好的提示。我確信有一個tpl的方式來做到這一點。 thx – Gullu

+0

是的,這可以很容易地使用FromAsync方法完成:http://msdn.microsoft.com/en-us/library/dd321311.aspx – BFree

0

爲什麼不這樣做:

Task.Factory.StartNew(()=>WorkerMethod()); 

,並定義WorkerMethod()爲:

void WorkerMethod() 
{ 
    RunSPAndCheckStuff(); // this blocks until finished 
    DoSomeMoreStuff(); // then this continuous 
} 

否則,請提供您想要完成什麼的更多細節。

3

所有這些東西在可以下載的異步語言擴展here和主頁here中尋址最好。

它引入了asyncawait關鍵字C#和VB,可以讓你寫的輕鬆,即使在一個單一的方法來回切換UI和後臺線程之間的代碼。編譯器會將其轉換爲任務,延續,錯誤捕捉等等,而不必擔心這些。你會感興趣的例子是:

public async void AsyncSwitchToCPU() { 
    Console.WriteLine("On the UI thread."); 

    // Switch to a thread pool thread: 
    await new SynchronizationContext().SwitchTo(); 

    Console.WriteLine("Starting CPU-intensive work on background thread..."); 
    int result = DoCpuIntensiveWork(); 
    Console.WriteLine("Done with CPU-intensive work!"); 

    // Switch back to UI thread 
    await Application.Current.Dispatcher.SwitchTo();     

    Console.WriteLine("Back on the UI thread. Result is {0}.", result); 
} 

public int DoCpuIntensiveWork() 
{ 
    // Simulate some CPU-bound work on the background thread: 
    Thread.Sleep(5000); 
    return 123; 
} 

這甚至有一個上線許可證(有一些保留從MS)。非常優雅的東西從F#借用。

RGDS格特 - 揚

+0

哇。整齊的東西。但有點矯枉過正,因爲我的簡單需求。我會閱讀這個。謝謝 – Gullu

相關問題