【问题标题】:C# SynchronizationC# 同步
【发布时间】:2010-07-16 16:18:40
【问题描述】:

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

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() 同步执行(并且是“短期运行”任务,例如

我不能使用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();
        }
    }
}

谁能把我推向正确的方向?

【问题讨论】:

    标签: c# winforms asynchronous


    【解决方案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
        }
    }
    

    这是最简单的解决方法,我不知道为什么我在星期五没有看到它...

    【讨论】:

      【解决方案2】:

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

      Application.DoEvents();
      

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

      你有类似的东西

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

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

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

      //关闭顶部:正如我所见,您的 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");
              }
          }
      }
      

      但是恕我直言,那将是不好的风格;)

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

      【讨论】:

        猜你喜欢
        • 2012-04-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多