C#同步

C#同步,c#,winforms,asynchronous,C#,Winforms,Asynchronous,我有一个关于同步的问题: private void ProcessStuff(Task sometask, Form progressform) { if (sometask.foo == "A") DoStuff(); //This one is SYNchronous else { ThirdPartyObject Q = new ThirdPartyObject(); Q.ProgessChanged += dele

我有一个关于同步的问题:

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);
对于这个项目,我一直在使用.NET2.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();
        }
    }
}

有人能把我推向正确的方向吗?

如果我正确理解你的需求,用一种方法是无法做到这一点的。 是的,除了

Application.DoEvents();
主要问题是,您希望使用基于过程的方法,但应该基于消息。 我会尽力解释的

你有点像

public partial class MyForm : Form
{
    ProgressBar progress;
    Button startTaskButton;
    void OnClick_startTaskButton();
您希望在后台使用线程/进程/BackgroundWorker或线程池启动一些耗时的任务。您需要该表单与用户交互,并在所述任务执行期间向用户显示任务进度

因此,您需要至少中断ProgressStaff两种方法:第一种方法将开始执行任务,第二种方法将在任务完成事件时做出反应

//顶部:正如我看到的,您的ThirdPartyObject类没有接收表单的实例,所以您应该手动同步

因此,您的代码如下所示:

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");
        }
    }
}
但我认为那将是一种糟糕的风格;)


(我不检查这段代码是否已编译,并且假设您在这方面没有问题)

如果我正确理解您的需求,那么用一种方法是无法做到这一点的。 是的,除了

Application.DoEvents();
主要问题是,您希望使用基于过程的方法,但应该基于消息。 我会尽力解释的

你有点像

public partial class MyForm : Form
{
    ProgressBar progress;
    Button startTaskButton;
    void OnClick_startTaskButton();
您希望在后台使用线程/进程/BackgroundWorker或线程池启动一些耗时的任务。您需要该表单与用户交互,并在所述任务执行期间向用户显示任务进度

因此,您需要至少中断ProgressStaff两种方法:第一种方法将开始执行任务,第二种方法将在任务完成事件时做出反应

//顶部:正如我看到的,您的ThirdPartyObject类没有接收表单的实例,所以您应该手动同步

因此,您的代码如下所示:

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");
        }
    }
}
但我认为那将是一种糟糕的风格;)


(我不检查这段代码是否已编译,假设您没有问题)

我决定以不同的方式处理它

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
    }
}
专用队列myqueue;
私有void Main(){
//做事
//填充队列
ProcessQueue();
}
私有void ProcessQueue(){
如果(myque.count>1)
ProcessStuff(myque.Dequeue());
其他的
MessageBox.Show(“完成!”);
}
私有void ProcessStuff(任务sometask,表单progressform)
{
if(sometask.foo==“A”){
DoStuff();//这个是同步的
ProcessQueue();
}
其他的
{
第三方对象Q=新的第三方对象();
Q.ProgressChanged+=委托(对象发送方,ProgressChangedEventArgs e){
进度表。显示进度(如进度百分比);
};
Q.TaskCompleted+=委托(对象发送方,TaskResult){
ProcessQueue();
};
Q.Execute(“X”、“Y”、“Z”);//这个执行异步
}
}

这是最简单的修复方法,我不知道为什么我在周五没有看到…

我决定以不同的方式处理它

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
    }
}
专用队列myqueue;
私有void Main(){
//做事
//填充队列
ProcessQueue();
}
私有void ProcessQueue(){
如果(myque.count>1)
ProcessStuff(myque.Dequeue());
其他的
MessageBox.Show(“完成!”);
}
私有void ProcessStuff(任务sometask,表单progressform)
{
if(sometask.foo==“A”){
DoStuff();//这个是同步的
ProcessQueue();
}
其他的
{
第三方对象Q=新的第三方对象();
Q.ProgressChanged+=委托(对象发送方,ProgressChangedEventArgs e){
进度表。显示进度(如进度百分比);
};
Q.TaskCompleted+=委托(对象发送方,TaskResult){
ProcessQueue();
};
Q.Execute(“X”、“Y”、“Z”);//这个执行异步
}
}
这是最简单的修复方法,我不知道为什么我在周五没有看到它