2010-07-16 56 views
1

我有關於同步的問題:)C#同步

private void ProcessStuff(Task sometask, Form progressform) 
{ 
    if (sometask.foo == "A") 
     DoStuff(); //This one is SYNchronous 
    else 
    { 
     ThirdPartyObject Q = new ThirdPartyObject(); 
     Q.ProgessChanged += delegate(object sender, ProgressChangedEventArgs e) { 
      progressform.ShowProgress(e.ProgressPercentage); 
     }; 
     Q.TaskCompleted += delegate(object sender, TaskResult result) { /* ??? */ }; 
     Q.Execute("X", "Y", "Z"); //This one executes ASYNchronous 
    } 
} 

DoStuff(執行同步(並且是 「短時間運行」 的任務,例如< 1秒)。另一方面,第三方的.Execute方法同步執行A。我希望ProcessStuff方法始終同步執行;所以我希望它在Q.Execute完成時返回。完成後,Q會引發TaskCompleted事件。但我也想報告它的進展。

我不能使用ManualResetEvent,因爲.WaitOne()方法將阻止當前線程,從而阻止報告進度。爲隊列中的每個對象調用ProcessStuff方法,並且該隊列中的任務需要按順序執行,而不是並行執行。

while (MyQueue.Count > 0) 
    ProcessStuff(MyQueue.Dequeue(), MyProgressDialog); 

我,對於這個項目,堅持與.net 2.0

這是星期五晚上和我累了,所以我可能忽略的東西,但我不知道如何解決這個問題。這有效;但我不認爲這是要走的路:

private void ProcessStuff(Task sometask, Form progressform) 
{ 
    ... 
     Q.TaskCompleted += delegate(object sender, TaskResult result) { /* ??? */ }; 
     Q.Execute("X", "Y", "Z"); //This one executes ASYNchronous 
     while (Q.IsBusy) { 
      //I Could Thread.Sleep(10) here... 
      Application.DoEvents(); 
     } 
    } 
} 

任何人都可以推動我在正確的方向嗎?

回答

1

我決定以不同的方式處理它;

private Queue<Task> myqueue; 

private void Main() { 
    //Do stuff 
    //Fill queue 
    ProcessQueue();   
} 
private void ProcessQueue() { 
    if (myqeue.count>1) 
     ProcessStuff(myqeue.Dequeue()); 
    else 
     MessageBox.Show("Done!"); 
} 
private void ProcessStuff(Task sometask, Form progressform) 
{ 
    if (sometask.foo == "A") { 
     DoStuff(); //This one is SYNchronous 
     ProcessQueue(); 
    } 
    else 
    { 
     ThirdPartyObject Q = new ThirdPartyObject(); 
     Q.ProgessChanged += delegate(object sender, ProgressChangedEventArgs e) { 
      progressform.ShowProgress(e.ProgressPercentage); 
     }; 
     Q.TaskCompleted += delegate(object sender, TaskResult result) { 
      ProcessQueue(); 
     }; 
     Q.Execute("X", "Y", "Z"); //This one executes ASYNchronous 
    } 
} 

這是最簡單的解決,我沒有得到一個線索,爲什麼我沒有看到,上週五...

0

如果我正確理解您的需求,則無法在一種方法中執行此操作。 是,除了

Application.DoEvents(); 

您要使用基於過程的方法的主要問題,但你應該基於消息。 我會盡力解釋。

您有類似

public partial class MyForm : Form 
{ 
    ProgressBar progress; 
    Button startTaskButton; 
    void OnClick_startTaskButton(); 

你想使用線程/進程/ BackgroundWorker的線程池或啓動在後臺一些耗時的任務。並且您需要該窗體與用戶進行交互,並在執行提到的任務期間向他顯示任務進度。

所以你需要打破你的ProgressStaff至少兩個方法:第一個將啓動任務執行,第二個將對任務完成事件作出反應。

// Off top:當我看到你的ThirdPartyObject類沒有收到Form的實例,所以你應該手動同步。

所以您的代碼將是這樣的:

void OnClick_startTaskButton() 
{ 
    ProcessStuff(GetTask(), this); 
} 

private void ProcessStuff(Task sometask, Form progressform) 
{ 
    if (sometask.foo == "A") 
     DoStuff(); //This one is SYNchronous 
    else 
    { 
     ThirdPartyObject Q = new ThirdPartyObject(); 
     Q.ProgessChanged += delegate(object sender, ProgressChangedEventArgs e) 
      { TaskProgessChanged(sender, e); }; 
     Q.TaskCompleted += delegate(object sender, TaskResult result) 
      { TaskCompleted(sender, result); }; 
     Q.Execute("X", "Y", "Z"); //This one executes ASYNchronous 
    } 
} 

void TaskProgessChanged(object sender, ProgressChangedEventArgs e) 
{ 
    if (InvokeRequired) Invoke(TaskProgessChanged, new object[] {sender, e}); 
    else ShowProgress(e.ProgressPercentage); 
} 

void TaskCompleted(object sender, TaskResult result) 
{ 
    if (InvokeRequired) Invoke(TaskComplete, new object[] {sender, result}); 
    else { 
     MessageBox.Show("Task is completed with result :" + result.ToString()); 
    } 
} 

======================

好吧,如果你真的要摔倒了你ProcessStuff方法執行同步,並在同一時間形式反映進展,並不能分割ProcessStuff爲兩種方法 - 你可以修改我的解決方案分爲以下方式:

private void ProcessStuff(Task sometask, Form progressform) 
{ 
    ProcessStuff(sometask, progressform, true); 
} 

private void ProcessStuff(Task sometask, Form progressform, bool isNewTask) 
{ 
    if (isNewTask) 
     if (sometask.foo == "A") 
      DoStuff(); //This one is SYNchronous 
     else 
     { 
      ThirdPartyObject Q = new ThirdPartyObject(); 
      Q.ProgessChanged += delegate(object sender, ProgressChangedEventArgs e) { 
       progressform.ShowProgress(e.ProgressPercentage); 
      }; 
      Q.TaskCompleted += delegate(object sender, TaskResult result) 
       { ProcessStuff(sometask, this, false); }; 
      Q.Execute("X", "Y", "Z"); //This one executes ASYNchronous 
     } 
    else 
    { 
     if (InvokeRequired) Invoke(TaskComplete, new object[] {sender, result, isNewTask}); 
     else { 
      //Task is completed 
      MessageBox.Show("Task is completed"); 
     } 
    } 
} 

但恕我直言,這將是不良作風;)

(我不檢查此代碼編譯並假設你有沒有問題與)