简体   繁体   English

防止多个异步操作

[英]Preventing Multiple Async Operations

i am working on some code where a timer tick every seconds and and get data from Webservice and Shows in on WInform , 我正在编写一些代码,其中计时器每秒钟滴答一次 ,并从Webservice获取数据并在WInform上显示,

What is the best approach to not run Multiple operations at same time ? 不同时运行多个操作的最佳方法是什么?

operation should run if previous operation completed and not running. 如果先前的操作已完成但未运行,则应运行该操作。

the code is 代码是

  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)

        }
    }

Just use a one-shot timer. 只需使用一个计时器。 If you use System.Timers.Timer then set its AutoReset property to false and use Start() at the end of your Elapsed event handler to restart it, typically in a finally block. 如果使用System.Timers.Timer,则将其AutoReset属性设置为false,并在Elapsed事件处理程序的末尾使用Start()来重新启动它,通常是在finally块中。 If you use System.Threading.Timer then construct it with a period of 0. Call its Change() method in the callback to recharge it. 如果使用System.Threading.Timer,则以0 周期构造它。在回调中调用其Change()方法为它充电。

Particularly in the case of System.Timers.Timer, it is pretty important that you do it this way. 特别是在System.Timers.Timer的情况下,以这种方式执行非常重要。 There's no upper bound on the number of threadpool threads it will start to call your Elapsed event handler. 它将开始调用Elapsed事件处理程序的线程池线程数没有上限。 If the machine is loaded, it can take a while for them to actually start running. 如果计算机已加载,则它们可能需要一段时间才能真正开始运行。 With plenty of opportunity for more than one to start running at the same time. 有很多机会可以同时开始多个。 And making it difficult to stop the timer. 而且很难停止计时器。

you can just disable the timer till one operation completes or set some field on completion (maybe better a ManualResetEventSlim because of multithreading). 您可以只禁用计时器,直到一个操作完成或在完成时设置某些字段为止(由于多线程,最好使用ManualResetEventSlim)。

Or have a look at the reactive extensions - there are a lot of good examples for such things. 或查看反应式扩展-有很多很好的例子。

You can find many samples here: 101 LINQ Samples , and very good intros here: Beginner's Guide to the Reactive Extensions . 您可以在这里找到许多示例: 101个LINQ示例 ,以及以下非常好的介绍: 《 Reactive Extensions入门指南》 And finally Somasegar has one blog-post that is very similar to your problem with Rx: Reactive Extensions for .NET (webservice call of bingtranslate with all you ever need ;) ) 最后,Somasegar的博客文章与Rx的问题非常相似: .NET的Reactive Extensions (使用bingtranslate的webservice调用可满足您的所有需求;))

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

I suppose you need something like operation queue. 我想您需要像操作队列这样的东西。 You need one separate thread which will check if this queue contains tasks and first task in queue is not running. 您需要一个单独的线程,该线程将检查此队列中是否包含任务,并且队列中的第一个任务未运行。 Then if task available you will run this task. 然后,如果任务可用,您将运行此任务。
Another way is to check if queue contains running tasks after adding new task. 另一种方法是在添加新任务后检查队列是否包含正在运行的任务。 If there are no running task then you run first task in separate thread. 如果没有正在运行的任务,那么您将在单独的线程中运行第一个任务。 Then after task finished you need to check if queue contains another task and to run next task. 然后,任务完成后,您需要检查队列是否包含另一个任务并运行下一个任务。

Another approach would be not to use a timer at all. 另一种方法是根本不使用计时器。 Create a thread with a loop that waits on an event with a one second timeout. 创建一个带有循环的线程,该线程等待事件超时一秒。 When the timeout expires call the web service. 超时到期后,请调用Web服务。 Then call the delegate to update the form. 然后呼叫代表以更新表格。 When you want to close the app, set the event. 当您要关闭应用程序时,请设置事件。 When the thread sees the event was set it can exit the loop and terminate. 当线程看到事件已设置时,它可以退出循环并终止。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM