[英]C# Synchronization
我有一個關於同步的問題:
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();
}
}
}
誰能向正確的方向推我?
我決定以不同的方式處理它;
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
}
}
這是最簡單的解決方法,對於為什么我在星期五沒看到這個,我一無所知。
如果我正確理解您的需求,則無法用一種方法來執行此操作。 是的,除了
Application.DoEvents();
您要使用的主要問題是基於過程的方法,但是應該基於消息。 我會盡力解釋。
你有類似的東西
public partial class MyForm : Form
{
ProgressBar progress;
Button startTaskButton;
void OnClick_startTaskButton();
您想使用Thread / Process / BackgroundWorker或ThreadPool在后台啟動一些耗時的任務。 並且您需要Form與用戶交互,並在執行任務時向他顯示任務進度。
因此,您需要至少中斷兩個方法:第一個方法將開始執行任務,第二個方法將對任務完成事件做出反應。
//頂部:據我所知,您的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方法同步執行並且同時Form反映進度,並且不能將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");
}
}
}
但是恕我直言,這將是不好的風格;)
(我不檢查此代碼是否已編譯,並且假設您對此沒有問題)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.