简体   繁体   English

与无限循环异步

[英]Async with Infinite Loop

I have a list of data sets that need to be updated real time. 我有一个需要实时更新的数据集列表。 I would like to process 10 out of 100+ at a time and then once one is done grab the next oldest line. 我想一次处理100个中的10个,然后一个完成后抓住下一个最老的线。 Basically keep this loop going for an infinite amount of time. 基本上保持这个循环无限的时间。 I am quite new to the world of Threading and been poking around at AsyncTask. 我对线程世界很陌生,一直在寻找AsyncTask。 Is there an example of this anyone can point me to? 有没有人能指出这个例子? I have googled quite a bit but can't find exactly what i'm looking for. 我用谷歌搜索了一下,但找不到我正在寻找的东西。

At least with .Net 4.5 async programming has becoming very sugary if you know what I mean. 如果你知道我的意思,至少使用.Net 4.5异步编程变得非常含糖。

Here is a simple set of examples: 这是一组简单的例子:

public async void DoAsync()
{
      await Task.Run( () =>
      { 
         // Do task! 
      } );
}

public async Task<string> GetStringAsync()
{
       string s = "";
       await Task.Run( () =>
       {
            for(int I = 0; I < 9999999; I++)
            {
                   s += I.ToString();
            }
       }
       return s;
}

Helpful Resources 有用的资源

http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx

AsyncTask is better suited to one-off operations. AsyncTask更适合一次性操作。 For an ongoing task you can consider a worker thread. 对于正在进行的任务,您可以考虑工作线程。

Disclaimer: I don't claim this is the best way to do it, but it should give you some ideas and stuff to read up on. 免责声明:我不认为这是最好的方法,但它应该给你一些想法和东西来阅读。

    public class ThreadingSample : IDisposable
{
    private Queue<SomeObject> _processingQueue = new Queue<SomeObject>();
    private Thread _worker;
    private volatile bool _workerTerminateSignal = false;
    private EventWaitHandle _waitHandle = new EventWaitHandle(false, EventResetMode.AutoReset);

    public bool HasQueuedItem
    {
        get
        {
            lock(_processingQueue)
            {
                return _processingQueue.Any();
            }
        }
    }

    public SomeObject NextQueuedItem
    {
        get
        {
            if ( !HasQueuedItem )
                return null;

            lock(_processingQueue)
            {
                return _processingQueue.Dequeue();
            }
        }
    }

    public void AddItem(SomeObject item)
    {
        lock(_processingQueue)
        {
            _processingQueue.Enqueue(item);
        }
        _waitHandle.Set();
    }
    public ThreadingSample()
    {
        _worker = new Thread(ProcessQueue);
        _worker.Start();
    }

    private void ProcessQueue()
    {
        while(!_workerTerminateSignal)
        {
            if ( !HasQueuedItem )
            {
                Console.WriteLine("No items, waiting.");
                _waitHandle.WaitOne();
                Console.WriteLine("Waking up...");
            }
            var item = NextQueuedItem;
            if (item != null)   // Item can be missing if woken up when the worker is being cleaned up and closed.
                Console.WriteLine(string.Format("Worker processing item: {0}", item.Data));
        }
    }

    public void Dispose()
    {
        if (_worker != null)
        {
            _workerTerminateSignal = true;
            _waitHandle.Set();
            if ( !_worker.Join( TimeSpan.FromMinutes( 1 ) ) )
            {
                Console.WriteLine("Worker busy, aborting the thread.");
                _worker.Abort();
            }
            _worker = null;
        }
    }

    public class SomeObject
    {
        public string Data
        {
            get;
            set;
        }
    }
}

Testing it I use a Unit test to kick it off. 测试它我使用单元测试启动它。 You can extend the unit test into a proper test to ensure that actions are being performed as expected. 您可以将单元测试扩展到适当的测试,以确保按预期执行操作。 In my case they're a good initial assertion to spike out behaviour. 在我的情况下,他们是一个很好的初步断言,以扼杀行为。

        [Test]
    public void TestThreading()
    {
        using ( var sample = new ThreadingSample() )
        {
            sample.AddItem(new ThreadingSample.SomeObject {Data = "First Item"});
            sample.AddItem(new ThreadingSample.SomeObject {Data = "Second Item"});
            Thread.Sleep(50);
            sample.AddItem(new ThreadingSample.SomeObject {Data = "Third Item"});
        }

    }

Relevant output from the test: 测试的相关输出:

------ Test started: Assembly: NHMapping.dll ------ ------测试开始:汇编:NHMapping.dll ------

Worker processing item: First Item 工人处理项目:第一项
Worker processing item: Second Item 工人处理项目:第二项
No items, waiting. 没有物品,等待。
Waking up... 起来...
No items, waiting. 没有物品,等待。
Waking up... 起来...
Worker processing item: Third Item 工人处理项目:第三项
No items, waiting. 没有物品,等待。
Waking up... 起来...

1 passed, 0 failed, 0 skipped, took 0.12 seconds (Ad hoc). 1次传递,0次失败,0次跳过,耗时0.12秒(Ad hoc)。

Here you can see the worker going to sleep, then waking up to process items in the queue. 在这里,您可以看到工作人员进入睡眠状态,然后醒来处理队列中的项目。 Technically you can use a list, then fetch 10 items from the list before releasing it from the lock and process those 10 items before checking the list again. 从技术上讲,您可以使用列表,然后从列表中获取10个项目,然后再从锁定中释放它并处理这10个项目,然后再次检查列表。

When the class is disposed it releases the loop then waits a moment for the worker thread to terminate before aborting. 当该类被释放时,它释放循环,然后等待工作线程在中止之前终止。 Here you'd probably want to check for any outstanding items and either log that they will not be processed, or persist them to file for later processing. 在这里,您可能希望检查是否有任何未完成的项目,并记录它们将不会被处理,或者将它们保存到文件中以供以后处理。

Edit: I found the issue with the double-event... A better implementation would be to use a ManualReset on the EventWaitHandle 编辑:我发现了双重事件的问题...一个更好的实现是使用ManualResetEventWaitHandle

private EventWaitHandle _waitHandle = new EventWaitHandle(false, EventResetMode.ManualReset);

Then when handling the case where you process an item, resent the handle: 然后在处理处理项目的情况时,重新发送句柄:

                var item = NextQueuedItem;
            if (item != null)   // Item can be missing if woken up when the worker is being cleaned up and closed.
            {
                Console.WriteLine(string.Format("Worker processing item: {0}", item.Data));
                _waitHandle.Reset();
            }

This produces the better test results: 这会产生更好的测试结果:

------ Test started: Assembly: NHMapping.dll ------ ------测试开始:汇编:NHMapping.dll ------

Worker processing item: First Item 工人处理项目:第一项
Worker processing item: Second Item 工人处理项目:第二项
No items, waiting. 没有物品,等待。
Waking up... 起来...
Worker processing item: Third Item 工人处理项目:第三项
No items, waiting. 没有物品,等待。
Waking up... 起来...

1 passed, 0 failed, 0 skipped, took 0.13 seconds (Ad hoc). 1次传递,0次失败,0次跳过,耗时0.13秒(Ad hoc)。

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

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