代码之家  ›  专栏  ›  技术社区  ›  RobIII Lukas

C#同步

  •  1
  • RobIII Lukas  · 技术社区  · 15 年前

    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-synchronous。我希望方法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();
            }
        }
    }
    

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

    2 回复  |  直到 15 年前
        1
  •  1
  •   RobIII Lukas    15 年前

    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
        }
    }
    

    这是最简单的解决办法,我不知道为什么我没有看到周五。。。

        2
  •  0
  •   VMykyt    15 年前

    是的,除了

    Application.DoEvents();
    

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

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

    您希望在后台使用Thread/Process/BackgroundWorker或ThreadPool启动一些耗时的任务。您需要该表单与用户交互,并向用户显示所述任务执行期间的任务进度。

    因此,您需要至少中断ProgressStaff两个方法:第一个方法将启动任务执行,第二个方法将在任务完成事件时作出反应。

    //Off-top:正如我看到的那样,你的第三个partyobject类没有收到表单的实例,所以你应该手动同步。

    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());
        }
    }
    

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

    真正地

    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");
            }
        }
    }
    

    但我认为那是不好的风格;)

    推荐文章