【问题标题】:Preventing Multiple Async Operations防止多个异步操作
【发布时间】:2011-09-10 12:47:37
【问题描述】:

我正在编写一些代码,其中 计时器每秒滴答一次,并从 Webservice 获取数据并在 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)

        }
    }

【问题讨论】:

  • 不应该运行还是应该等到前一个完成?
  • 所有给出的答案都是有效的解决方案。但是,如果您需要快速而肮脏,最简单的方法可能是使用一个简单的布尔变量作为您的“锁”。在计时器滴答开始时将锁定设置为 true,并在结束时将其设置为 false。先检查锁,如果是真的,不要再做。准确地说,当您访问 lock 变量时,将其包装在一个临界区 (i.e. lock(this) {...}) 中,这样就没有两个计时器滴答可以同时读取 lock 变量——尽管它基于一个具有大足够的滴答间隔,发生这种情况的可能性很小。

标签: c# .net winforms asynchronous


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    或者看看响应式扩展 - 有很多很好的例子。

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

    【讨论】:

    • 它可以工作,但它有点慢,我需要最快的解决方案它的外汇数据,我每 200 毫秒刷新一次
    【解决方案3】:

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

    【讨论】:

    • 如果你使用它,webresponse 类可能会卡住。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-07-16
        • 1970-01-01
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-25
        相关资源
        最近更新 更多