2012-11-21 220 views
3

我有一个需要实时更新的数据集列表。我想每次处理100个以上的10个,然后一旦完成,就抓住下一个最老的线。基本上保持这个循环持续无限的时间。我对线程的世界很陌生,并且一直在AsyncTask中探索。有没有人可以指点我的例子?我GOOGLE了很多,但无法找到我正在寻找的东西。与无限循环异步

回答

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个项目。

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

编辑:我发现这个问题有双重事件...更好的实现是使用在EventWaitHandle

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

一个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)。

+0

第二项和第三项之间的双重唤醒有点令人感兴趣,可能是由于我用每个AddItem调用触发了'EventWaitHandle'。 –

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