相关疑难解决方法(0)

如何写一个"等待"的方法?

我终于研究了async和await关键字,我有点"得到",但我见过的所有例子都在.Net框架中调用异步方法,例如这个调用HttpClient.GetStringAsync().

我不太清楚的是这种方法会发生什么,以及我如何编写自己的"等待"方法.它是否像包装我想在Task中异步运行的代码并返回那样简单?

c# async-await

61
推荐指数
5
解决办法
4万
查看次数

"等待Task.Yield()"及其替代品

如果我需要推迟代码执行,直到UI线程消息循环的未来迭代之后,我可以这样做:

await Task.Factory.StartNew(
    () => {
        MessageBox.Show("Hello!");
    },
    CancellationToken.None,
    TaskCreationOptions.None,
    TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)

这将类似于await Task.Yield(); MessageBox.Show("Hello!");,除了我有一个选项可以取消任务,如果我想.

在使用默认同步上下文的情况下,我可以类似地使用await Task.Run继续池线程.

事实上,我喜欢Task.Factory.StartNewTask.Run更多Task.Yield,因为他们都明确定义了延续代码的范围.

那么,在什么情况下await Task.Yield()实际上有用呢?

.net c# task-parallel-library async-await

21
推荐指数
3
解决办法
1万
查看次数

为什么从Async CTP/Release中删除"SwitchTo"?

我今天尝试使用SwitchTo方法切换到GUI线程,并发现我解除它的示例不起作用,仅仅是因为该方法不存在.

然后我在这里发现了这个模糊:

我们摆脱它的原因是因为它太危险了.另一种方法是在TaskEx.Run中捆绑你的代码......

我的问题很简单:为什么它很危险?使用它会带来哪些特定的危险?

请注意,我确实阅读了该帖子的其余部分,因此我确实理解这里存在技术限制.我的问题仍然是,如果我意识到这一点,为什么它很危险

我正在考虑重新实现帮助方法来给我指定的功能,但如果有一些根本性的破坏,除了有人认为它是危险的,我不会这样做.

具体来说,非常天真,这是我如何考虑实现所需的方法:

public static class ContextSwitcher
{
    public static ThreadPoolContextSwitcher SwitchToThreadPool()
    {
        return new ThreadPoolContextSwitcher();
    }

    public static SynchronizationContextSwitcher SwitchTo(this SynchronizationContext synchronizationContext)
    {
        return new SynchronizationContextSwitcher(synchronizationContext);
    }
}

public class SynchronizationContextSwitcher : INotifyCompletion
{
    private readonly SynchronizationContext _SynchronizationContext;

    public SynchronizationContextSwitcher(SynchronizationContext synchronizationContext)
    {
        _SynchronizationContext = synchronizationContext;
    }

    public SynchronizationContextSwitcher GetAwaiter()
    {
        return this;
    }

    public bool IsCompleted
    {
        get
        {
            return false;
        }
    }

    public void OnCompleted(Action action) …
Run Code Online (Sandbox Code Playgroud)

c# asynchronous async-await async-ctp

13
推荐指数
2
解决办法
1114
查看次数

当我指定ConfigureAwait(false)时,为什么我仍然在主线程上?

我试图了解async/await关键字的工作原理.我在WPF窗口上有一个textblock绑定到TextBlockContent字符串属性和一个触发单击ChangeText()的按钮.

这是我的代码:

public async void ChangeText()
{
     string mystring = await TestAsync();
     this.TextBlockContent= mystring;
}

private async Task<string> TestAsync()
{
     var mystring = await GetSomeString().ConfigureAwait(false);
     mystring = mystring + "defg";
     return mystring;
}

private Task<string> GetSomeString()
{
    return Task.Run(() =>
    {
        return "abc";
    });
}
Run Code Online (Sandbox Code Playgroud)

从我的读数中,我了解到ConfigureAwait设置为false将允许我指定我不想保存当前上下文以用于需要在await关键字之后执行的Task的"rest".

在调试之后,我意识到当我有这段代码时,有时代码在主线程之后运行:await GetSomeString().ConfigureAwait(false); 虽然我特意添加了配置等待.

我原以为它总是运行在与进入Task之前的那个线程不同的线程上运行.

有人可以帮我理解为什么吗?

非常感谢你

c# wpf async-await

7
推荐指数
1
解决办法
307
查看次数

使用自己的ThreadPool继续任务

是否可以强制继续使用async-await语句在自定义ThreadPool的线程上运行?

上下文:我正在运行一个ASP应用程序并在后台做了相当多的工作.我正在通过自编写的ThreadPool完成所有工作,但如果我使用async-await模式,则延续总是在名为"Worker Thread"的线程上运行.我很确定这是来自默认ThreadPool的线程,它也用于处理HTTP请求.由于默认ThreadPool的所有线程都忙着继续我的后台工作,这导致这些请求的饥饿.

.net c# task-parallel-library async-await

7
推荐指数
2
解决办法
828
查看次数

Task.Yield是否真的在当前上下文中运行延续?

尽管已经编写了多年的C#,但我不是async的专家,但是在阅读了一些MSDN博客文章之后,AFAICT:

  • 等待(例如Task)可以捕获或不捕获当前SynchronizationContext.
  • 一个SynchronizationContext大致相当于一个线程:如果我在UI线程和呼叫上await task,这"流动语境",延续在UI线程上运行.如果我调用await task.ConfigureAwait(false),则继续在一些随机线程池线程上运行,该线程可能是/可能不是UI线程.
  • 对于awaiters:OnCompleted流上下文,UnsafeOnCompleted并不流动上下文.

好了,有了这个,我们来看看Roslyn生成的代码await Task.Yield().这个:

using System;
using System.Threading.Tasks;

public class C {
    public async void M() {
        await Task.Yield();
    }
}
Run Code Online (Sandbox Code Playgroud)

这个编译器生成的代码的结果(你可以在这里验证自己):

public class C
{
    [CompilerGenerated]
    [StructLayout(LayoutKind.Auto)]
    private struct <M>d__0 : IAsyncStateMachine
    {
        public int <>1__state;

        public AsyncVoidMethodBuilder <>t__builder;

        private YieldAwaitable.YieldAwaiter <>u__1;

        void IAsyncStateMachine.MoveNext()
        {
            int num = this.<>1__state;
            try
            {
                YieldAwaitable.YieldAwaiter yieldAwaiter;
                if (num != 0) …
Run Code Online (Sandbox Code Playgroud)

.net c# asynchronous task async-await

6
推荐指数
2
解决办法
467
查看次数

TaskEx.Yield(的TaskScheduler)

上个月我问了以下问题,这导致我学到了TaskEx.Yield:

异步方法在第一次"等待"之前是否有昂贵的代码?

但是,我已经意识到这个方法实际上将所有后续代码提交给环境TaskScheduler.在真正的DI精神中,我们的团队同意尽可能避免使用环境实例,所以我想知道是否可以明确指定TaskScheduler使用?

像下面这样的东西会很棒:

public static YieldAwaitable Yield(TaskScheduler taskScheduler)
{
    return new YieldAwaitable(taskScheduler);
}
Run Code Online (Sandbox Code Playgroud)

但是,Async CTP的当前实现仅提供:

public static YieldAwaitable Yield()
{
    return new YieldAwaitable(SynchronizationContext.Current ?? TaskScheduler.Current);
}
Run Code Online (Sandbox Code Playgroud)

以下是否会提供可接受的有效替代方案?

await Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.None, this.TaskScheduler);
Run Code Online (Sandbox Code Playgroud)

.net c# task-parallel-library async-ctp .net-4.5

3
推荐指数
1
解决办法
2443
查看次数

将异步方法的执行推送到线程池线程

考虑这个Windows窗体代码(可以编写类似的WPF模拟代码):

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void TraceThreadInfo([CallerMemberName]string callerName = null)
    {
        Trace.WriteLine($"{callerName} is running on UI thread: {!this.InvokeRequired}");
    }

    private void DoCpuBoundWork([CallerMemberName]string callerName = null)
    {
        TraceThreadInfo(callerName);
        for (var i = 0; i < 1000000000; i++)
        {
            // do some work here
        }
    }

    private async Task Foo()
    {
        DoCpuBoundWork();
        await Bar();
    }

    private async Task Bar()
    {
        DoCpuBoundWork();
        await Boo();
    }

    private async Task Boo()
    {
        DoCpuBoundWork();
        // e.g., saving …
Run Code Online (Sandbox Code Playgroud)

c# wpf winforms async-await

3
推荐指数
1
解决办法
653
查看次数