与无限循环异步

时间:2012-11-21 03:15:55

标签: c# c#-4.0 asynchronous

我有一个需要实时更新的数据集列表。我想一次处理100个中的10个,然后一个完成后抓住下一个最老的线。基本上保持这个循环无限的时间。我对线程世界很陌生,一直在寻找AsyncTask。有没有人能指出这个例子?我用谷歌搜索了一下但找不到我想要的东西。

2 个答案:

答案 0 :(得分:5)

至少使用.Net 4.5,如果你知道我的意思,异步编程已变得非常含糖。

以下是一组简单的例子:

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;
}

有用的资源

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

答案 1 :(得分:2)

AsyncTask更适合一次性操作。对于正在进行的任务,您可以考虑工作线程。

免责声明:我并不认为这是最好的方法,但它应该给你一些想法和内容供你阅读。

    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;
        }
    }
}

测试它我使用单元测试开始它。您可以将单元测试扩展到适当的测试,以确保按预期执行操作。在我的情况下,他们是一个很好的初步主张,可以扼杀行为。

        [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"});
        }

    }

测试的相关输出:

  

------测试开始:汇编:NHMapping.dll ------
  
  工人加工项目:第一项目   工人加工项目:第二项目   没有物品,等待。
  醒来......
  没有物品,等待。
  醒来......
  工人加工项目:第三项目   没有物品,等待。
  醒来......
  
  1次通过,0次失败,0次跳过,耗时0.12秒(Ad hoc)。

在这里,您可以看到工作人员进入睡眠状态,然后醒来处理队列中的项目。从技术上讲,您可以使用列表,然后从列表中获取10个项目,然后再从锁定中释放它们并处理这10个项目,然后再次检查列表。

当类被释放时,它释放循环然后等待工作线程在中止之前终止。在这里,您可能希望检查是否有任何未完成的项目,并记录它们将不会被处理,或者将它们保存到文件中以供以后处理。

编辑:我发现了双重事件的问题......更好的实施方法是在ManualReset上使用EventWaitHandle

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

然后在处理处理项目的情况时,重新发送句柄:

                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();
            }

这会产生更好的测试结果:

  

------测试开始:汇编:NHMapping.dll ------
  
  工人加工项目:第一项目   工人加工项目:第二项目   没有物品,等待。
  醒来......
  工人加工项目:第三项目   没有物品,等待。
  醒来......
  
  1通过,0失败,0跳过,花了0.13秒(Ad hoc)。