简体   繁体   English

如何创建一个内部带有等待方法的线程?

[英]How to create a thread with await methods inside?

I'm creating a thread我正在创建一个线程

Thread MyThread = new Thread(async () => await MyTask());
MyThread.Start(); 

It kinda doesn't make sense and that's the question of how to create it properly.这有点没有意义,这就是如何正确创建它的问题。

MyTask is an unending task which periodically starts cpu intensive work MyTask 是一个无休止的任务,它会定期启动 CPU 密集型工作

async Task MyTask ()
    {
        while (true)
        {                
            await Task.Run(() => CPU_Load());
            await Task.Delay(1000).ConfigureAwait(false);
        }
    }

CPU_Load is a method where work is being done CPU_Load 是一种正在完成工作的方法

void CPU_Load ()
    {            
       *CPU_Load*    
    }


      

How about the original async strategy back when Main couldn't be async.当 Main 不能异步时,原始的异步策略怎么样。 Start your thread with a non-async function (or delegate or lambda).使用非异步 function(或委托或 lambda)启动您的线程。 In that function that simply says WhatIWantToDoAsync().Wait();在那个 function 中,简单地说 WhatIWantToDoAsync().Wait(); that is async and returns a Task.那是异步的并返回一个任务。 Your thread function never returns, so waiting for it isn't going to do much.您的线程 function 永远不会返回,所以等待它不会做太多。 – Flydog57 – Flydog57

The Thread constructor does not understand async delegates. Thread构造函数不理解async委托。 You can read about this here:你可以在这里阅读:

The "proper" way to execute periodically some code depends on where you want to run your code.定期执行某些代码的“正确”方式取决于您要在哪里运行代码。 Do you have any reason to run it on a dedicated thread?你有什么理由在专用线程上运行它吗? Some components are thread-affine, and require to be manipulated by the same thread for the entirety of their existence.一些组件是线程仿射的,并且在它们存在的整个过程中都需要由同一线程操作。 If you have this (not very common) requirement, you can use the Thread constructor without async/await:如果你有这个(不是很常见的)需求,你可以使用没有 async/await 的Thread构造函数:

var myThread = new Thread(() =>
{
    while (true)
    {
        var delayTask = Task.Delay(1000);
        CPU_Load();
        delayTask.Wait();
    }
});
myThread.IsBackground = true;
myThread.Start();

Notice how the Task.Delay task is created before the CPU-bound operation, and then waited afterwards.注意Task.Delay任务是如何在 CPU-bound 操作之前创建的,然后在之后等待。 This way the interval between two subsequent invocations of the CPU_Load method will be constant.这样, CPU_Load方法的两次后续调用之间的间隔将保持不变。 It will not depend on the duration of the call itself.它不取决于通话本身的持续时间。

If you don't need a dedicated thread, you can do the work more economically by using reusable threads from the ThreadPool .如果您不需要专用线程,则可以通过使用ThreadPool中的可重用线程来更经济地完成工作。 Which is exactly what your current MyTask implementation does, with the Task.Run method inside.这正是您当前的MyTask实现所做的,其中包含Task.Run方法。 To start the task is as easy as invoking the asynchronous method:启动任务就像调用异步方法一样简单:

var myTask = MyTask();

Now the task is running, and will continue running until the process terminates, or the CPU_Load invocation fails, whatever comes first.现在任务正在运行,并将继续运行直到进程终止,或者CPU_Load调用失败,无论先发生什么。

Another way to implement the asynchronous MyTask method would be to wrap the whole loop in a Task.Run , instead of having the Task.Run inside the loop.实现异步MyTask方法的另一种方法是将整个循环包装在Task.Run中,而不是将Task.Run放在循环中。 Functionally and performance-wise is almost identical:在功能和性能方面几乎相同:

var myTask = Task.Run(async () =>
{
    while (true)
    {
        var delayTask = Task.Delay(1000);
        CPU_Load();
        await delayTask;
    }
});

I have omitted the ConfigureAwait(false) because it's not really needed.我省略了ConfigureAwait(false) ,因为它并不是真正需要的。 The ThreadPool does not have a synchronization context that can be captured by the await . ThreadPool没有可被await捕获的同步上下文。

You could also consider using a Timer to run periodically your work, but I consider the Task -based approach to be superior.您也可以考虑使用Timer定期运行您的工作,但我认为基于Task的方法更好。 It's quite tricky to enforce a non-overlapping execution policy with constant interval using a Timer .使用Timer强制执行具有恒定间隔的非重叠执行策略非常棘手。 Caveats:注意事项:

  1. TheSystem.Timers.Timer class is not thread-safe. System.Timers.Timer class 不是线程安全的。
  2. It allows overlapping invocations of the event handler.它允许事件处理程序的重叠调用。
  3. It swallows any exceptions thrown inside the handler.它吞下处理程序中抛出的任何异常。

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

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