如何提高.NET中任务的优先级?

时间:2019-01-09 10:13:33

标签: c# task-parallel-library

我有一个程序可以生成带有随机内容的txt文件。必须生成许多文档,因此我使用Tasks可以更快地完成工作。我想每隔几秒钟通知用户进度(例如:“从100000中生成了50000个文档”)。我创建另一个任务RecordProgress(),它每3秒记录一次进度。

但是,如果程序生成许多任务,则RecordProgress()永远不会运行。如果程序仅生成4个任务,则RecordProgress()正确运行,即。每3秒被调用一次。但是,如果程序生成许多任务,则仅在处理接近完成时才运行RecordProgress()。

是否有任何方法可以提高RecordProgress()任务的优先级?

我已经尝试记录每个任务的进度,但是这会向控制台生成太多日志消息,这严重降低了我的程序速度。

我尝试登录每个任务并等待两次日志之间的3秒,但是如果程序生成50个任务,则50条消息将同时记录到控制台,这再次使我的程序变慢并且不必要。我希望每3秒向控制台发送一条日志消息。

public void RecordProgress() 
{
        Stopwatch sw = new Stopwatch();
        sw.Start();

        //only record data while this generator is generating
        while (_processing)
        {
            if(sw.ElapsedMilliseconds < _logFrequency)
                continue;

            Console.WriteLine("Generated " + _docsGenerated + " documents.");
            sw.Restart();
        }
}

public void GenerateDocs()
{
    List<Task> tasks = new List<Task>();

    _processing = true;
    for (i = 0; i < 50; i ++)
    {
        tasks.Add(Task.Run(() => DoWork());
    }

    //task which records progress
    //ONLY runs if not many tasks are created above
    Task.Run(() => RecordProgress());

    Task.WaitAll(tasks.ToArray());
}

我希望RecordProgress()任务每3秒运行一次,而不管该程序生成的任务数量如何。

编辑:根据评论,我删除了Thread.Sleep()的使用。但是,这只会延迟我的RecordProgress()任务的启动。

我试图在RecordProgress()中使用秒表仅每3秒记录一次进度,但这极大地降低了程序的性能。

一个新问题:如何在不使用严重影响性能的计时器的情况下记录任务的进度?

2 个答案:

答案 0 :(得分:0)

在原始情况下,您创建许多任务并耗尽线程池中的可用线程。最后运行ReportProgress会延迟其执行,直到大多数其他任务完成为止。我看到您更正了您的代码。

关于优先权问题。请记住,您无法更改任务的优先级。您可以通过实现自己的TaskScheduler来实现类似目的,但是默认情况下,所有任务都具有正常的优先级。

如果您确实需要以更高的优先级运行任务,则需要创建一个Thread并将其优先级设置为更高/最高。您应该非常小心。

答案 1 :(得分:-1)

我找到了:

我创建了一个Stopwatch对象,该对象需要使用锁才能访问。在我的DoWork()任务结束时,该任务将锁定并检查自程序上次记录以来已过去了多少时间。如果超过3秒,任务将记录进度并重置秒表对象。 RecordProgress()任务不再是必需的。

public void GenerateDocs()
{
    List<Task> tasks = new List<Task>();

    lock (_lockForLog)
    {
        _swForLogging.Start();
    }
    _processing = true;
    for (i = 0; i < 50; i ++)
    {
        tasks.Add(Task.Run(() => DoWork());
    }

    Task.WaitAll(tasks.ToArray());

    lock (_lockForLog)
    {
        _swForLogging.Stop();
    }
}

public void DoWork(){
    //do work

    lock (_lockForLog)
    {
        if (_swForLogging.ElapsedMilliseconds > 3000)
        {
            Console.WriteLine("Generated " + _docsGenerated + " documents.");
            _swForLogging.Restart();
        }
    }
}