c# - Threading.Timer 在控制台应用程序中停止

标签 c# .net console

我正在使用一个字典,其中包含 ID 作为键和队列作为值。我有一个线程写入队列,另一个线程从队列读取,因此我需要使用 .NET 4.0 中引入的并发结构。作为其中的一部分,我尝试编写一个测试应用程序来填充队列,但我遇到了一个问题,计时器在大约 10 秒后停止。我真的不明白为什么,因为没有什么可捕获的,没有错误消息或任何东西可以给我关于可能出现问题的提示。

有人可以向我解释一下为什么计时器在大约 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; }
}

最佳答案

最有可能的是,计时器超出了范围并被收集。在外部范围声明计时器。即:

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

另外,我想你会发现BlockingCollection比 ConcurrentQueue 更容易使用。 BlockingCollection 围绕并发集合封装了一个非常好的 API,使得在删除内容时更容易在队列上进行非繁忙等待。在其默认配置中,它使用 ConcurrentQueue 作为后备存储。要使用它,您只需将代码中的 ConcurrentQueue 替换为 BlockingCollection,并将调用 Enqueue 更改为调用 Add。如:

for (int i = 0; i < 5; i++)
{
    foreach (var pipe in _pipes)
    {
        pipe.Value.Add(
            new TestObject { Name = DateTime.Now.ToString("o") + "-" + i });
    }
}

关于c# - Threading.Timer 在控制台应用程序中停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15482093/

相关文章:

c# - 如何以编程方式更改默认音频输入设备

.net - VB.NET 窗口屏幕截图 (ALT+PRINTSCREEN)

.net - 截至 2010 年,哪个是最流行的 .Net O/R-Mapper?

使用命令行通过 Jar 文件进行 Java IO

c# - 在扩展方法中使用 .net core 依赖项

c# - 如何使用 selenium rc for c# 处理验证消息?

c# - 最大化控制台窗口 - C#

c# - 控制台的调整大小事件

c# - 公共(public)语言运行时无法设置断点

c# - 代码分析警告 2214 - 如何最好地修复?