简体   繁体   English

如何增加.NET中任务的优先级?

[英]How to increase priority of a Task in .NET?

I have a program that generates txt files with randomized contents. 我有一个程序可以生成带有随机内容的txt文件。 Many documents have to be generated, so I use Tasks to get the work done faster. 必须生成许多文档,因此我使用Tasks可以更快地完成工作。 I want to notify the user of the progress that's being made every few seconds (ex: "Generated 50000 documents out of 100000"). 我想每隔几秒钟通知用户进度(例如:“从100000中生成了50000个文档”)。 I create another Task, RecordProgress(), which records progress every 3 seconds. 我创建另一个任务RecordProgress(),它每3秒记录一次进度。

However, if the program generates many tasks, the RecordProgress() never runs. 但是,如果程序生成许多任务,则RecordProgress()永远不会运行。 If the program only generates 4 tasks, then RecordProgress() runs correctly ie. 如果程序仅生成4个任务,则RecordProgress()正确运行,即。 gets called every 3 seconds. 每3秒被调用一次。 However, if the program generates many tasks, RecordProgress() only runs once processing is/close to being finished. 但是,如果程序生成许多任务,则仅在处理接近完成时才运行RecordProgress()。

Is there any way to increase the priority of the RecordProgress() task? 有什么办法可以提高RecordProgress()任务的优先级吗?

I've tried logging progress in each task, but that generates too many log messages to the console, which severely slows down my program. 我已经尝试记录每个任务的进度,但这会向控制台生成太多日志消息,这严重降低了我的程序速度。

I've tried logging in each task and waiting 3 seconds between logs, but if the program generates 50 tasks, then 50 messages will be logged to the console at the same time, which once again slows down my program and is unnecessary. 我尝试登录每个任务并等待两次日志之间的3秒钟,但是如果程序生成50个任务,则50条消息将同时记录到控制台,这又使我的程序变慢,并且不必要。 I'd rather have ONE log message to the console every 3 seconds. 我希望每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());
}

I'd like the RecordProgress() task to run every 3 seconds regardless of the number of tasks generated by this program. 我希望RecordProgress()任务每3秒运行一次,而不管该程序生成的任务数量如何。

Edit: As per the comments, I removed the use of Thread.Sleep(). 编辑:根据评论,我删除了Thread.Sleep()的使用。 However, that only delayed the starting of my RecordProgress() task. 但是,这只会延迟我的RecordProgress()任务的启动。

I've attempted to use a Stopwatch in RecordProgress() to only record progress every 3 seconds, but it greatly slows the performance of my program. 我试图在RecordProgress()中使用秒表仅每3秒记录一次进度,但这极大地降低了程序的性能。

So new question: how to record progress of tasks without using a timer that heavily impacts performance? 如此新的问题:如何在不使用严重影响性能的计时器的情况下记录任务的进度?

In the original case, you create many tasks and exhaust the available threads in the Thread Pool. 在原始情况下,您将创建许多任务并耗尽线程池中的可用线程。 Running ReportProgress last delays its execution until most of the other tasks are complete. 最后运行ReportProgress延迟其执行,直到大多数其他任务完成为止。 I see you corrected you code. 我看到您更正了您的代码。

As for the priority question. 至于优先问题。 Have in mind that you cannot change the priority of a task. 请记住,您无法更改任务的优先级。 You may achieve something like it by implementing your own TaskScheduler, but by default all tasks run a normal priority. 您可以通过实现自己的TaskScheduler来实现类似目的,但是默认情况下,所有任务都具有正常的优先级。

If you really need to run a task in higher priority, you need to create a Thread and set its priority to higher / highest. 如果确实需要以更高的优先级运行任务,则需要创建一个Thread并将其优先级设置为更高/最高。 Something you should be very careful about. 您应该非常小心。

I've found it: 我发现了:

I've created a Stopwatch object that requires the use of a lock to access. 我创建了一个Stopwatch对象,该对象需要使用锁才能访问。 At the end of my DoWork() task, the task locks and checks how much time has passed since the program last logged. 在我的DoWork()任务结束时,该任务将锁定并检查自程序上次记录以来已过去了多少时间。 If over 3 seconds have passed, the task logs progress and resets the Stopwatch object. 如果超过3秒,任务将记录进度并重置秒表对象。 The RecordProgress() task is no longer necessary. 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();
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM