[英]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.