在另一个线程运行的异步功能线程、功能

2023-09-03 08:47:16 作者:似水流年,择一人终老

我评估异步CTP。

我如何开始在另一个线程池中的线程执行异步功能?

 静态异步任务测试()
{
    //做一些事情,等待的东西
}

静态无效的主要(字串[] args)
{
    //是否有更优雅的方式来编写线下?
    VAR T = TaskEx.Run(()=>测试()等待());

    //做更多的在这同一主题
    t.Wait(); //等待绝不仅仅只是这一个任务,这只是一个例子
}
 

解决方案

我是新的(我的处女后)堆栈溢出,但我为此感到兴奋不已,你问的是异步CTP,因为我在团队的工作就可以了微软:)

我想我明白你的目标是什么,并有你在做正确的几件事情,让你在那里。

我想你想要的:

 静态异步任务测试()
{
    //做一些事情,等待的东西
}

静态无效的主要(字串[] args)
{
    //在CTP,使用Task.RunEx(...)运行异步方法或异步LAMBDA
    //在.NET线程池
    VAR T = TaskEx.RunEx(试验);
    //以上只是速记
    VAR T = TaskEx.RunEx(新Func键<任务>(测试));
    //因为C#的自动包装方法分为委托给你。

    //做更多的在这同一主题
    t.Wait(); //等待绝不仅仅只是这一个任务,这只是一个例子
}
 

Task.Run与Task.RunEx

Java高级看这篇就足够了 高级知识汇总

由于该CTP在.NET 4.0顶部安装,我们并不想修补的实际 System.Threading.Tasks.Task 请在mscorlib中。相反,操场上的API被命名为FooEx当他们发生冲突。

为什么我们称他们中的一些运行(...)和一些 RunEx(...)?究其原因是因为在方法重载的重新设计,我们已经不是我们发布的CTP时尚未完成的。在我们当前的工作codeBase的,我们实际上不得不调整的C#方法重载规则稍微使正确的事情发生了异步lambda表达式 - 它可以返回无效工作任务< T>

的问题是,当异步方法或lambda表达式返回工作任务< T> ,他们居然穿上吨有在返回前pression外的任务类型,因为将自动为您生成的任务,方法或lambda的调用的一部分。这强烈地在我们看来是一个正确的经验,为code清晰,虽然这确实使事情完全不同之前,由于一般return语句的前pression直接转换为方法或lambda的返回类型。

所以因此,无论是异步无效 lambda表达式和异步工作 lambda表达式支持返回; 不带参数。因此,需要在方法重载澄清,以决定哪一个选择。因此,唯一的原因,你有两种运行(......)和RunEx(...)是如此,我们会确保有对异步CTP的其他部分更高质量的支持下,由当时的PDC 2010命中。

如何考虑异步方法/ lambda表达式

我不知道这是否是一个容易混淆的地方,但我想我会提到它 - 当你正在编写一个异步方法或异步拉姆达,它可以采取谁在调用它的某些特性。这是pdicated两点$ P $:

在类型上,你正等待 也可能是同步上下文(上视)

该CTP设计计谋和我们目前的内部设计都非常的模式为基础的,这样的API提供商可以帮助充实一个充满活力的一套东西,你可以等待。这可以根据上你等待的类型不同而不同,和普通类型是工作

工作的等待执行是非常合理的,并按照当前线程的的SynchronizationContext 来决定如何推迟工作。在这你已经在一个WinForms或WPF消息循环的话,那么你的延迟执行会回来同一消息循环(因为如果你使用的BeginInvoke()的休息的方法)。如果你等待一个任务,你就已经在.NET线程池,那么其余的方法将恢复对线程池的一个线程(但不一定是同一台完全一致),因为它们汇集到开始和最有可能你很高兴去的第一个可用的池线程。

注意有关使用wait()的方法

在你的样品,你使用: 变种T = TaskEx.Run(()=>测试()等待());

什么,做的是:

在周围的线程同步调用TaskEx.Run(...),以线程池执行一个lambda。 在一个线程池线程被指定为拉姆达,并调用您的异步方法。 的异步方法测试()从拉姆达调用。因为拉姆达正在执行的线程池,里面的测试()的任何延续可以在线程池中的任何线程中运行。 的拉姆达实际上并不腾出线程的堆栈,因为它没有在等待着它。第三方物流在这种情况下,行为取决于是否测试()等待()调用之前实际完成。然而,在这种情况下,还有一种现实的可能性,你将被阻塞线程池中的线程在等待测试()执行完在不同的线程。

这就是'等待'运营商的主要好处是,它可以让你增加$ C,后来执行$ C - 但没有挡住原来的线程。在线程池的情况下,可以达到更好的线程利用。

让我知道,如果您有任何关于异步CTP其他问题的VB或C#,我很乐意听到他们的声音:)

I'm evaluating the Async CTP.

How can I begin execution of an async function on another thread pool's thread?

static async Task Test()
{
    // Do something, await something
}

static void Main( string[] args )
{
    // Is there more elegant way to write the line below?
    var t = TaskEx.Run( () => Test().Wait() );

    // Doing much more in this same thread
    t.Wait(); // Waiting for much more then just this single task, this is just an example
}

解决方案

I'm new (my virginal post) to Stack Overflow, but I'm jazzed that you're asking about the Async CTP since I'm on the team working on it at Microsoft :)

I think I understand what you're aiming for, and there's a couple of things you're doing correctly, to get you there.

What I think you want:

static async Task Test()
{
    // Do something, await something
}

static void Main(string[] args)
{
    // In the CTP, use Task.RunEx(...) to run an Async Method or Async Lambda
    // on the .NET thread pool
    var t = TaskEx.RunEx(Test);
    // the above was just shorthand for
    var t = TaskEx.RunEx(new Func<Task>(Test));
    // because the C# auto-wraps methods into delegates for you.

    // Doing much more in this same thread
    t.Wait(); // Waiting for much more then just this single task, this is just an example
}

Task.Run vs. Task.RunEx

Because this CTP installs on top of .NET 4.0, we didn't want to patch the actual System.Threading.Tasks.Task type in mscorlib. Instead, the playground APIs are named FooEx when they conflicted.

Why did we name some of them Run(...) and some of the RunEx(...)? The reason is because of redesigns in method overloading that we hadn't completed yet by the time we released the CTP. In our current working codebase, we've actually had to tweak the C# method overloading rules slightly so that the right thing happens for Async Lambdas - which can return void, Task, or Task<T>.

The issue is that when async method or lambdas return Task or Task<T>, they actually don't have the outer task type in the return expression, because the task is generated for you automatically as part of the method or lambda's invocation. This strongly seems to us like the right experience for code clarity, though that does make things quite different before, since typically the expression of return statements is directly convertible to the return type of the method or lambda.

So thus, both async void lambdas and async Task lambdas support return; without arguments. Hence the need for a clarification in method overload resolution to decide which one to pick. Thus the only reason why you have both Run(...) and RunEx(...) was so that we would make sure to have higher quality support for the other parts of the Async CTP, by the time PDC 2010 hit.

How to think about async methods/lambdas

I'm not sure if this is a point of confusion, but I thought I'd mention it - when you are writing an async method or async lambda, it can take on certain characteristics of whoever is invoking it. This is predicated on two things:

The type on which you are awaiting And possibly the synchronization context (depending on above)

The CTP design for await and our current internal design are both very pattern-based so that API providers can help flesh out a vibrant set of things that you can 'await' on. This can vary based on the type on which you're awaiting, and the common type for that is Task.

Task's await implementation is very reasonable, and defers to the current thread's SynchronizationContext to decide how to defer work. In the case that you're already in a WinForms or WPF message loop, then your deferred execution will come back on the same message loop (as if you used BeginInvoke() the "rest of your method"). If you await a Task and you're already on the .NET threadpool, then the "rest of your method" will resume on one of the threadpool threads (but not necessarily the same one exactly), since they were pooled to begin with and most likely you're happy to go with the first available pool thread.

Caution about using Wait() methods

In your sample you used: var t = TaskEx.Run( () => Test().Wait() );

What that does is:

In the surrounding thread synchronously call TaskEx.Run(...) to execute a lambda on the thread pool. A thread pool thread is designated for the lambda, and it invokes your async method. The async method Test() is invoked from the lambda. Because the lambda was executing on the thread pool, any continuations inside Test() can run on any thread in the thread pool. The lambda doesn't actually vacate that thread's stack because it had no awaits in it. The TPL's behavior in this case depends on if Test() actually finished before the Wait() call. However, in this case, there's a real possibility that you will be blocking a thread pool thread while it waits for Test() to finish executing on a different thread.

That's the primary benefit of the 'await' operator is that it allows you to add code that executes later - but without blocking the original thread. In the thread pool case, you can achieve better thread utilization.

Let me know if you have other questions about the Async CTP for VB or C#, I'd love to hear them :)

 
精彩推荐
图片推荐