防止多个异步操作

时间:2011-09-10 12:47:38

标签: c# .net winforms asynchronous

我正在处理一些代码,其中计时器每秒都会打勾并从Web服务获取数据并显示在WInform上,

同时运行多项操作的最佳方法是什么?

如果先前的操作已完成且未运行,则应运行该操作。

代码是

  public void loadbalance()
    {
       try { //Get Data from Internet }
       catch { }
    }

    delegate void loadbalancedelegate();

    public void loadBalanceAsync()
    {
        loadbalancedelegate worker = new loadbalancedelegate(loadbalance);
        AsyncCallback LoadbalnceCallBack = new AsyncCallback(loadbalanceCompleted);

        AsyncOperation async = AsyncOperationManager.CreateOperation(null);
        worker.BeginInvoke(LoadbalnceCallBack,async);
    }

    public void loadbalanceCompleted(IAsyncResult result)
    {
         loadbalancedelegate worker = (loadbalancedelegate)          ((AsyncResult)result).AsyncDelegate;
        AsyncOperation async = (AsyncOperation)result.AsyncState;

        worker.EndInvoke(result);
    }

    delegate void setControlsBalanceDelegate(BalanceOB ball);

    void setControlsBalance(BalanceOB ball)
    {
        if (this.InvokeRequired)
            this.Invoke(new setControlsBalanceDelegate(this.setControlsBalance), new
            object[] { ball });
        else
        {    //Update Data on Form (Windows App)

        }
    }

5 个答案:

答案 0 :(得分:2)

只需使用一次性计时器。如果使用System.Timers.Timer,则将其AutoReset属性设置为false,并使用Elapsed事件处理程序末尾的Start()重新启动它,通常在finally块中。如果您使用System.Threading.Timer,则使用 period 为0构造它。在回调中调用其Change()方法为其充电。

特别是在System.Timers.Timer的情况下,以这种方式执行它是非常重要的。它将开始调用您的Elapsed事件处理程序的线程池线程数没有上限。如果机器已加载,它们可能需要一段时间才能真正开始运行。有很多机会让不止一个人同时开始跑步。并且很难停止计时器。

答案 1 :(得分:1)

你可以禁用定时器,直到一个操作完成或在完成时设置一些字段(由于多线程,可能更好的是ManualResetEventSlim)。

或者看看反应性扩展 - 这些事情有很多很好的例子。

您可以在此处找到许多示例:101 LINQ Samples,以及非常好的介绍:Beginner's Guide to the Reactive Extensions。 最后,Somasegar有一篇博文与你在Rx上的问题非常相似:Reactive Extensions for .NET(bingtranslate的webservice调用你需要的所有东西;)

答案 2 :(得分:0)

考虑在System.Threading.Tasks名称空间中使用Task.Wait()

答案 3 :(得分:0)

我想你需要像操作队列这样的东西。您需要一个单独的线程来检查此队列是否包含任务,队列中的第一个任务是否未运行。然后,如果任务可用,您将运行此任务 另一种方法是在添加新任务后检查队列是否包含正在运行的任务。如果没有正在运行的任务,则在单独的线程中运行第一个任务。然后在任务完成后,您需要检查队列是否包含另一个任务并运行下一个任务。

答案 4 :(得分:0)

另一种方法是根本不使用计时器。使用循环创建一个线程,该循环等待事件超时一秒。超时到期时调用Web服务。然后调用委托来更新表单。如果要关闭应用程序,请设置事件。当线程看到事件被设置时,它可以退出循环并终止。