等待异步呼叫完成 [英] Waiting for an Asynchronous Call to be finished

查看:57
本文介绍了等待异步呼叫完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好,
在我的表单上,有一个按钮可以启动多个作业.
后面的方法是:
1.收集文件
2.复制
3.接下来的复制方法等待完成.

复制方法被异步调用(由于ProgressBar和冻结"形式.
我正在运行复制,我应该在哪里以及如何强制复制,直到复制完成?下一方法(3)不应在此之前开始.我尝试了EndInvoke,IAsyncResult等,但是我只是感到困惑,next-Method不等待复制...
代码:

Hello,
on my form there is a button starting several jobs.
The methods behind are:
1. gathering Files
2. copying
3. next Method WAITING for copying to be finished.

Copying-Method is called asynchronously (because of ProgressBar and "freezing" form.
I got copying running, where and how should I FORCE copying wait, till copying is finished? Next-method (3) shouldn''t be started before. I experimented with EndInvoke, IAsyncResult etc. but I only got confused and next-Method doesn''t wait for copying...
The code:

delegate void ShowProgressDelegate(string target, int totalDigits, int digitsSoFar);
delegate void CalcDelegate(int digits);
void ShowProgress(string target, int totalDigits, int digitsSoFar)
        {
            //
            if (lblProgressBar.InvokeRequired == false)
            {
                lblProgressBar.Text = target;
                pBar1.Maximum = totalDigits;
                pBar1.Value = digitsSoFar;
            }
            else //
            {
                ShowProgressDelegate showProgress = new ShowProgressDelegate(ShowProgress);
                //Invoke..
                IAsyncResult ar = BeginInvoke(showProgress, new object[] {target,totalDigits,digitsSoFar });
                EndInvoke(ar);
            }

        }

//Button-Routine...
private void CopyWithProgressBar(ArrayList myAl)
        {
            //ProgressBar einblenden..
            this.pBar1.Visible = true;
            CalcDelegate calcDel = new CalcDelegate(DoJob);
            calcDel.BeginInvoke((int)myAl.Count, null, null);
           
        }

        private void DoJob(int digits)
        {
            Object[] jajco = myAl.ToArray();
            //ShowProgress
            ShowProgress("Kopieren: ", digits, 0);
            if(digits>0)
            {
                for (int x = 0; x < digits; x++)
                {
                    string input = jajco[x].ToString().Substring(0, jajco[x].ToString().IndexOf(","));
                    string target = jajco[x].ToString().Substring(jajco[x].ToString().IndexOf(",") + 1);
                    File.Copy(input, target, true);
                    //Show Progress..
                    ShowProgress("Kopieren: " + target, digits, x);
                }

            }
        }


感谢您的帮助.


Thank you for any help

推荐答案

使用异步委托调用,检测完成的最有用方法是使用回调.这是您可以适应的基本模板:

With asynchronous delegate invocation the most useful way to detect completion is to use a callback. This is a basic template which you can adapt:

using System.Runtime.Remoting.Messaging;

private delegate void ProcessingMethodDelegate();

public void StartAsync() {
  ProcessingMethodDelegate pm = new ProcessingMethodDelegate(ProcessingMethod);
  pm.BeginInvoke(AsyncComplete, null);
}

public void ProcessingMethod () {
   // do stuff
}

/// <summary>
/// Completion method called on a Threadpool thread
/// </summary>
public void AsyncComplete(IAsyncResult ar) {
  AsyncResult result = (AsyncResult)ar;
  try {
    ((ProcessingMethodDelegate)result.AsyncDelegate).EndInvoke(ar);
  } catch (Exception e) {
    // handle exception raised by ProcessingMethod
  } finally {
    // next actions
  }
}



在您的情况下,除非您真的非常希望使用异步委托,否则我建议您 Backgroundworker类 [ ^ ]具有进度和完成事件,这两个事件都在UI线程上引发.

无论您选择什么,下一个动作都是从完成处理程序中启动的,在UI应用程序中,这通常只不过是启用在后台任务期间被禁用的按钮.

针对您的评论:
通过一系列任务,必须结束,然后再开始下一个任务,您的代码必须执行此要求.

一种可能的解决方案是在一个线程中运行序列,即将整个序列作为一个后台操作运行.

例如



In your case, unless you really have a great desire to use asynchronous delegates, I would suggest the Backgroundworker class[^] which has progress and completion events, both of which are raised on the UI thread.

Whatever you choose the next action is initiated from the completion handler and in a UI application this is often nothing more than enabling buttons that were disabled for the duration of the background task.

In response to your comment:
With a sequence of tasks one must end before the next is allowed to start and your code has to enforce this requirement.

A possible solution is to run the sequence in one thread, i.e. run the whole sequence as one background operation.

e.g.

public void ProcessingMethod () {
  Task1();
  Task2();
  Task3();
}


另一种选择是我最初的建议,它是将每个异步任务的完成处理程序链接在一起,以使一个任务的完成开始下一个任务.

无论您使用Backgroundworker还是异步委托都不会影响程序的逻辑流程,只是正确地使它发生对程序员来说是更多的工作.


艾伦.


The alternative is my original suggestion which is to chain the completion handlers of each individual asynchronous task so that completion of one starts the next.

Whether you use Backgroundworker or asynchronous delegates makes no difference to the logical flow of the program, it is just that making it happen correctly is more work for the programmer.


Alan.


除了艾伦的解决方案.

调用根本不是呼叫.它用于收集调用所需的所有数据(代理实例加上参数),并将其排队到实际完成调用的UI线程中.它只能通过UI来完成.

同样,这些调用方法不仅是System.Windows.Forms.Conrol的,而且是System.Threading.Dispatcher的,这可以与Forms和WPF一起使用.

请查看它在过去的答案中的工作方式:
Control.Invoke()与Control.BeginInvoke() [ ^ ],
Treeview Scanner和MD5的问题 [用于线程通信和线程间调用的简单阻塞队列 [ ^ ].

—SA
In addition to the solution by Alan.

Invoke is not a call at all. It is used to collect all data needed to the call (delegate instance plus parameters) and queue it to the UI thread where the call is actually done. It can only be done with UI.

Also, these invocation methods are not only of the System.Windows.Forms.Conrol but also of System.Threading.Dispatcher, which can works with both Forms and WPF.

Please see how it works in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

Basically, it works only on UI threads (some mistakenly thinks it works for all thread because the Dispatcher can invoke anywhere, but in fact it is reduced to a simple call on a current thread!).

A special effort is needed to create such mechanism for other threads. I''ve done it, see full code and usage samples in my short Tips/Trick article here:
Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

—SA


这篇关于等待异步呼叫完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆