【问题标题】:Timer in Task not firing任务中的计时器未触发
【发布时间】:2014-02-09 09:45:59
【问题描述】:

下面的代码是从一个任务中调用的 t = new task(() => StartScanAsync(path)); 但定时器事件没有触发,定时器在 StartTimer 中启动。

private void StartScanAsync(string path)
{
    StartTimer();
    foreach (string fsPath in Alphaleonis.Win32.Filesystem.Directory.EnumerateFileSystemEntries(path, "*", SearchOption.AllDirectories, true))
    {
        Alphaleonis.Win32.Filesystem.FileInfo finfo = new Alphaleonis.Win32.Filesystem.FileInfo(fsPath);
        fileClass.AddFile(finfo);
        //  UpdateStatus(fsPath);
        UpdateTotalFilesScanned();
        TotalFileSize += finfo.Length;
        UpdateTotalFileSize(TotalFileSize);
        IdentifyFileType.FileType ft = FileType.LoadPathRet(fsPath);
        //  Application.DoEvents();
    }
    UpdateStatus("Done Scanning.");
    StopTimer();
}

我也尝试了 Parrallel.ForEach 并且遇到了同样的问题。

下面的代码应该启动一个计时器,在一个大型集合上运行 Parrallel.ForEach,然后停止计时器。但是,Timer 事件没有被触发...任何想法为什么以及如何解决这个问题?

StartTimer();
Parallel.ForEach(Alphaleonis.Win32.Filesystem.Directory.EnumerateFileSystemEntries(path, "*", SearchOption.AllDirectories), fsPath =>
{
    Alphaleonis.Win32.Filesystem.FileInfo finfo = new Alphaleonis.Win32.Filesystem.FileInfo(fsPath);
    fileClass.AddFile(finfo);
    UpdateStatus(fsPath);
    UpdateTotalFilesScanned();
    TotalFileSize += finfo.Length;
    UpdateTotalFileSize(TotalFileSize);
    // IdentifyFileType.FileType ft = FileType.LoadPathRet(fsPath);
    Application.DoEvents();
});
StopTimer();

第一个代码在不在任务中时工作,第二个代码不在任务中运行但仍然不工作。

所以澄清一下:
问题1)为什么定时器(System.Windows.Forms.Timer(我认为))不会在Task中触发,并且在Parallel.ForEach周围时也不会触发?

问题 2)如何在 Parallel.ForEach 任务和 Task 任务中每秒提高一次 Tick(以获取每秒扫描的文件)?

【问题讨论】:

  • 只是为了确定一下,你真的是Start()Task吗?
  • 是的,任务已启动。即使它不会触发 Tick 事件。

标签: c# timer task parallel.foreach


【解决方案1】:

.NET 提供了很多不同的计时器。你可以在这篇关于Comparing the Timer Classes in the .NET Framework Class Library的文章中找到详细的列表和解释。

问题是您使用的 System.Windows.Forms.Timer 应该只在 UI 线程上使用。在测试场景中,即使对于这样一个简单的情况,使用此计时器也无法正常工作:

Task.Factory.StartNew(() =>
{
    var timer = new Timer { Enabled = true, Interval = 1000 };
    timer.Tick += (s, e) => 
        Console.WriteLine("This will never be written to the console!");
});

我假设您在StartTimerStopTimer 方法中创建计时器或修改其属性。即使您在 UI 线程上创建计时器,您实际上也必须在同一个 UI 线程上设置 IntervalEnabled

由于您在不同的任务中使用计时器(通过使用 Task 或 Parallel.For),您必须使用不同的计时器,例如System.Threading.Timer

您的第二种情况可能相同,但如果不知道使用并行循环调用代码 sn-p 的代码,则很难判断。

【讨论】:

  • 今天试试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-01
  • 2015-06-03
相关资源
最近更新 更多