相关疑难解决方法(0)

为所有服务器端代码调用ConfigureAwait的最佳实践

当你有服务器端代码(即一些ApiController)并且你的函数是异步的 - 所以它们返回Task<SomeObject>- 你认为最好的做法是等待你调用的函数ConfigureAwait(false)吗?

我已经读过它更高效,因为它不必将线程上下文切换回原始线程上下文.但是,使用ASP.NET Web Api,如果您的请求是在一个线程上进行的,并且等待某些函数和调用ConfigureAwait(false),则可能会在返回ApiController函数的最终结果时将您置于不同的线程上.

我在下面输入了一个我正在谈论的例子:

public class CustomerController : ApiController
{
    public async Task<Customer> Get(int id)
    {
        // you are on a particular thread here
        var customer = await SomeAsyncFunctionThatGetsCustomer(id).ConfigureAwait(false);

        // now you are on a different thread!  will that cause problems?
        return customer;
    }
}
Run Code Online (Sandbox Code Playgroud)

c# task-parallel-library async-await asp.net-web-api

517
推荐指数
4
解决办法
18万
查看次数

正确使用Task.Run时和async-await时

我想问你关于正确架构何时使用的意见Task.Run.我在WPF .NET 4.5应用程序(使用Caliburn Micro框架)中遇到了滞后的UI.

基本上我在做(非常简化的代码片段):

public class PageViewModel : IHandle<SomeMessage>
{
   ...

   public async void Handle(SomeMessage message)
   {
      ShowLoadingAnimation();

      // Makes UI very laggy, but still not dead
      await this.contentLoader.LoadContentAsync();

      HideLoadingAnimation();
   }
}

public class ContentLoader
{
    public async Task LoadContentAsync()
    {
        await DoCpuBoundWorkAsync();
        await DoIoBoundWorkAsync();
        await DoCpuBoundWorkAsync();

        // I am not really sure what all I can consider as CPU bound as slowing down the UI
        await DoSomeOtherWorkAsync();
    }
}
Run Code Online (Sandbox Code Playgroud)

从我阅读/看到的文章/视频中,我知道await async不一定在后台线程上运行,并且需要在后台开始工作,需要等待它Task.Run(async () => …

c# asynchronous task async-await

288
推荐指数
2
解决办法
25万
查看次数

为什么我需要在所有传递闭包中使用ConfigureAwait(false)?

我正在学习async/await,在我读完这篇文章之后不要阻止异步代码

是async/await适用于IO和CPU绑定的方法

我从@Stephen Cleary的文章中注意到了一个提示.

使用ConfigureAwait(false)来避免死锁是一种危险的做法.您必须对阻塞代码调用的所有方法的传递闭包中的每个等待使用ConfigureAwait(false),包括所有第三方和第二方代码.使用ConfigureAwait(false)来避免死锁充其量只是一个黑客攻击.

它在我上面附上的帖子代码中再次出现.

public async Task<HtmlDocument> LoadPage(Uri address)
{
    using (var httpResponse = await new HttpClient().GetAsync(address)
        .ConfigureAwait(continueOnCapturedContext: false)) //IO-bound
    using (var responseContent = httpResponse.Content)
    using (var contentStream = await responseContent.ReadAsStreamAsync()
        .ConfigureAwait(continueOnCapturedContext: false)) //IO-bound
        return LoadHtmlDocument(contentStream); //CPU-bound
}
Run Code Online (Sandbox Code Playgroud)

据我所知,当我们使用ConfigureAwait(false)时,其余的异步方法将在线程池中运行.为什么我们需要在传递闭包中将它添加到每个等待中?我自己只是认为这是我所知道的正确版本.

public async Task<HtmlDocument> LoadPage(Uri address)
{
    using (var httpResponse = await new HttpClient().GetAsync(address)
        .ConfigureAwait(continueOnCapturedContext: false)) //IO-bound
    using (var responseContent = httpResponse.Content)
    using (var contentStream = await responseContent.ReadAsStreamAsync()) //IO-bound
        return LoadHtmlDocument(contentStream); //CPU-bound
}
Run Code Online (Sandbox Code Playgroud)

这意味着在使用块中第二次使用ConfigureAwait(false)是没用的.请告诉我正确的方法.提前致谢.

c# multithreading asynchronous

25
推荐指数
1
解决办法
6431
查看次数

等待任务完成后不返回

我遇到了一个任务正在完成但没有返回的问题.我在不同的服务器上有一个网站和一个Web服务.该网站调用Web服务,该服务使用具有函数myFunction()的库.如果我从Web服务的服务器上的控制台应用程序调用myFunction,它将按预期返回.但是,当我从网站拨打电话到Web服务来调用myFunction()时,它将进入"步骤3",而不是"步骤4".我有以下调用的简化版本.

private string myFunction()
{
    string myStr = myDoWork().GetAwaiter().GetResult();

    return myStr;
}

private async Task<string> myDoWork()
{
    logger.Debug("Step 1");
    string answer = await aFunction();

    logger.Debug("Step 4");

    return answer;
}

public async Task<string> aFunction()
{
    logger.Debug("Step 2");
    return await bFunction(CancellationToken.None);
}

AsyncLock myLock = new AsyncLock();
public Task<string> bFunction(CancellationToken cToken)
{
    return Task.Run(
        async () =>
        {
            using (await myLock(cToken))
            {
                logger.Debug("Step 3");
                result = "Hello";
                return result;
            }
        },
        cToken);
}
Run Code Online (Sandbox Code Playgroud)

我是异步和等待的新手,所以任何帮助都将不胜感激.

c# asynchronous

9
推荐指数
1
解决办法
4927
查看次数

具体来说,在Unity中,等待在哪里真正地返回到“哪里”?

在Unity中,说您有一个GameObject。因此,可能是劳拉·克罗夫特(Lara Croft),马里奥(Mario),愤怒的鸟,特定的立方体,特定的树或其他任何东西。

在此处输入图片说明

(回想一下,Unity不是OO,它是ECS。Component可以“附加”到s的s本身可以GameObject用OO语言创建,也可以不使用OO语言创建,但是Unity本身只是GameObjects 的列表和运行任何Components 的框架引擎。因此,实际上Unity当然是“完全”的单线程,甚至没有一种概念上的方法可以在另外1个线程上执行与“实际Unity”(“游戏对象列表”)相关的任何操作。)

所以说在多维数据集上,我们有一个Component称为Test

public class Test: MonoBehaviour {
Run Code Online (Sandbox Code Playgroud)

它确实具有Update伪函数,因此Unity知道我们要在每个帧中运行一些东西。

  private void Update() { // this is Test's Update call

     Debug.Log(ManagedThreadId); // definitely 101
     if (something) DoSomethingThisParticularFrame();
  }
Run Code Online (Sandbox Code Playgroud)

假设统一线程为“ 101”。

这样更新(实际上是任何游戏对象上任何框架的任何更新)都将打印101。

因此,由于某种原因,我们有时会选择每隔几秒钟运行一次DoSomethingThisFrame

因此,每一帧(显然,在“该” Unity线程上……有/只能有一个线程),Unity在各种游戏对象上运行所有Update调用。

因此,在一个特定的帧(比如说游戏的第819秒的第24帧)上,它确实DoSomethingThisParticularFrame为我们运行。

void DoSomethingThisParticularFrame() {

   Debug.Log(ManagedThreadId); // 101 I think
   TrickyBusiness();
}
Run Code Online (Sandbox Code Playgroud)

我认为这也会打印101。

async void TrickyBusiness() {

   Debug.Log("A.. " + ManagedThreadId); // 101 I think
   var aTask …
Run Code Online (Sandbox Code Playgroud)

.net c# multithreading unity-game-engine

4
推荐指数
1
解决办法
543
查看次数

为什么总是推荐使用 await 在每一行上写 ConfigureAwait(false) ,我真的需要它吗?

问题不在于 ConfigureAwait 做什么。但更确切地说,为什么我到处都能看到类似的东西

一般来说,是的。除非该方法需要其上下文,否则应为每个等待使用 ConfigureAwait(false)。

即他们建议我应该写

await Method1().ConfigureAwait(false);
await Method2().ConfigureAwait(false);
// Do something else
// ...
await Method3().ConfigureAwait(false);
await Method4().ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,只在一开始就重置上下文不会更清楚,就像

await Task.Yield().ConfigureAwait(false);
Run Code Online (Sandbox Code Playgroud)

它保证下面的代码将在没有同步上下文的情况下执行,不是吗?

即我读到如果该方法立即返回,则写一次 ConfigureAwait 可能不起作用。对我来说,显而易见的解决方案看起来像调用 ConfigureAwait(false) 肯定不会立即返回的东西,Task.Yield 是什么,对吧?

另外我知道 Task.Yield 不再包含 ConfigureAwait(不知道为什么,因为我知道它以前曾经有它),但是查看 Task.Yield 代码很容易编写自己的方法除了用空的同步上下文调用延续之外,什么都不做。

对我来说,阅读似乎要容易得多,尤其是当你写一次的时候写

await TaskUtility.ResetSyncContext();
Run Code Online (Sandbox Code Playgroud)

而不是在每一行上写 ConfigureAwait。

这会起作用(Task.Yield().ConfigureAwait(false) 或类似的自定义方法)还是我错过了什么?

c# async-await .net-core

4
推荐指数
1
解决办法
875
查看次数