2013-03-18 5 views
2

Я работаю со словарем, содержащим идентификатор в качестве ключа, и очередь в качестве значения. У меня есть один поток, записывающий в очереди, и другой поток, читаемый из очередей, поэтому мне нужно использовать Concurrent-структуры, которые были внедрены в .NET 4.0. В рамках этого я попытался написать тестовое приложение, чтобы заполнить очереди, но я столкнулся с проблемой, когда таймеры останавливались примерно через 10 секунд. Я действительно не понимаю, почему, поскольку нет ничего, что можно поймать, никакого сообщения об ошибке или чего-нибудь еще, чтобы дать мне подсказку о том, что может быть неправильным.Threading.Timer останавливается в консольном приложении

Так может кто-нибудь объяснить мне, почему таймер останавливается примерно через 10 секунд? Я пробовал это на двух разных компьютерах (как с использованием Visual Studio 2012, так и с .NET Framework 4.0).

class Program { 

    private readonly ConcurrentDictionary<int, ConcurrentQueue<TestObject>> _pipes = 
     new ConcurrentDictionary<int, ConcurrentQueue<TestObject>>(); 

    static void Main() { 
     Program program = new Program(); 
     program.Run(); 
     Console.Read(); 
    } 

    private void Run() { 
     _pipes[100] = new ConcurrentQueue<TestObject>(); 
     _pipes[200] = new ConcurrentQueue<TestObject>(); 
     _pipes[300] = new ConcurrentQueue<TestObject>(); 

     Timer timer = new Timer(WriteStuff, null, 0, 100); 
    } 

    private void WriteStuff(object sender) { 
     for (int i = 0; i < 5; i++) { 
      foreach (KeyValuePair<int, ConcurrentQueue<TestObject>> pipe in _pipes) { 
       pipe.Value.Enqueue(
        new TestObject { Name = DateTime.Now.ToString("o") + "-" + i }); 
      } 
      i++; 
     } 
     Console.WriteLine(DateTime.Now + "added stuff"); 
    } 
} 

internal class TestObject { 
    public string Name { get; set; } 
    public bool Sent { get; set; } 
} 

ответ

4

Скорее всего, таймер выходит из сферы действия и собирается. Объявите таймер во внешней области. То есть:

private Timer timer; 
private void Run() 
{ 
    ... 
    timer = new Timer(WriteStuff, null, 0, 100); 
} 

Кроме того, я думаю, вы обнаружите, что BlockingCollection легче работать, чем ConcurrentQueue. BlockingCollection обертывает очень приятный API вокруг параллельных коллекций, что упрощает выполнение незанятых ожиданий в очереди при удалении вещей. В своей конфигурации по умолчанию он использует ConcurrentQueue в качестве хранилища резервных копий. Все, что вам нужно сделать для его использования, заключается в замене ConcurrentQueue в вашем коде BlockingCollection и изменении сотового телефона Enqueue на вызов Add. Как в:

Смежные вопросы