相关疑难解决方法(0)

关于线程的混淆以及异步方法在C#中是否真正异步

我正在阅读async/await,什么时候Task.Yield可能有用,并且发现了这篇文章. 我从那篇文章中得到了关于下面的问题:

使用async/await时,无法保证在执行await时调用的方法FooAsync()实际上是异步运行的.内部实现可以使用完全同步的路径自由返回.

这对我来说有点不清楚,可能是因为我头脑中的异步定义没有排成一行.

在我看来,由于我主要做UI开发,异步代码是不在UI线程上运行的代码,而是在其他一些线程上.我想在我引用的文本中,如果一个方法阻塞在任何线程上(即使它是一个线程池线程),它也不是真正的异步.

题:

如果我有一个长时间运行的任务是CPU绑定的(假设它做了很多硬数学运算),那么异步运行该任务必须阻塞一些线程吗?有些东西实际上要做数学.如果我等待它,那么一些线程就会被阻止.

什么是真正的异步方法的例子,它们将如何实际工作?这些是否仅限于利用某些硬件功能的I/O操作,因此没有阻止任何线程?

.net c# asynchronous

48
推荐指数
5
解决办法
5516
查看次数

Task.Yield - 真实用法?

我一直在阅读有关Task.Yield,而且作为一名JavaScript开发,我可以告诉大家,就是它的工作是 完全相同一样setTimeout(function (){...},0);在让主单线程处理又名其他的东西方面:

"不要把所有的力量从时间上释放出来 - 所以其他人也会有一些......"

在js中,它特别适用于长循环.(不要让浏览器冻结......)

但我在这里看到了这个例子:

public static async Task < int > FindSeriesSum(int i1)
{
    int sum = 0;
    for (int i = 0; i < i1; i++)
    {
        sum += i;
        if (i % 1000 == 0) ( after a bulk , release power to main thread)
            await Task.Yield();
    }

    return sum;
}
Run Code Online (Sandbox Code Playgroud)

作为JS程序员,我可以理解他们在这里做了什么.

但作为一名C#程序员,我问自己:为什么不为它开一个任务呢?

 public static async Task < int > FindSeriesSum(int i1)
    {
         //do something.... …
Run Code Online (Sandbox Code Playgroud)

c# multithreading async-await c#-5.0 .net-4.5

38
推荐指数
3
解决办法
2万
查看次数

如何使用DoEvents()而不是"邪恶"?

简单的搜索DoEvents会带来很多结果,这些结果基本上会导致:

DoEvents是邪恶的.不要使用它.请改用线程.

一般引用的原因是:

  • 重新入侵问题
  • 表现不佳
  • 可用性问题(例如,在禁用的窗口上拖放)

但是一些值得注意的Win32功能,例如TrackPopupMenuDoDragDrop 执行自己的消息处理以保持UI响应,就像这样DoEvents.
然而,这些问题似乎都没有遇到过这些问题(性能,再入等等).

他们是如何做到的呢?他们如何避免引用的问题DoEvents?(或者他们?)

windows winapi doevents visual-c++ winforms

23
推荐指数
1
解决办法
8643
查看次数

"等待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
查看次数

库中的Task.Yield()需要ConfigureWait(false)

建议使用一个ConfigureAwait(false)当你可以随时,特别是在图书馆,因为它可以帮助避免死锁和提高性能.

我编写了一个大量使用异步的库(访问数据库的Web服务).图书馆的用户遇到了僵局,经过多次痛苦的调试和修补后,我将其追踪到了单独使用await Task.Yield().我使用过的其他任何地方.ConfigureAwait(false),但是不支持Task.Yield().

对于需要等效的情况,推荐的解决方案是Task.Yield().ConfigureAwait(false)什么?

我已经读过有关如何SwitchTo移除某个方法的内容.我可以看出为什么那可能是危险的,但为什么没有相应的Task.Yield().ConfigureAwait(false)

编辑:

为了提供我的问题的进一步背景,这里有一些代码.我正在实现一个开源库,用于访问支持异步的DynamoDB(作为AWS的服务的分布式数据库).IX-Async库IAsyncEnumerable<T>提供了许多操作返回.该库不提供从以"块"提供行的数据源生成异步枚举的好方法,即每个异步请求返回许多项.所以我有自己的通用类型.该库支持预读选项,允许用户指定在调用实际需要之前应该请求多少数据.MoveNext()

基本上,这是如何工作的,我通过调用GetMore()和传递这些块之间的状态来请求块.我将这些任务放入chunks队列并将它们出列并将它们转换为我放在单独队列中的实际结果.这个NextChunk()方法就是问题所在.根据值的不同,ReadAhead我会在完成最后一个(最多)之后保持获取下一个块,直到需要一个值但不可用(无)或仅获取超出当前使用值的下一个块(一些).因此,获取下一个块应该并行/不阻止获取下一个值.枚举器代码是:

private class ChunkedAsyncEnumerator<TState, TResult> : IAsyncEnumerator<TResult>
{
    private readonly ChunkedAsyncEnumerable<TState, TResult> enumerable;
    private readonly ConcurrentQueue<Task<TState>> chunks = new ConcurrentQueue<Task<TState>>();
    private readonly Queue<TResult> results = new Queue<TResult>();
    private CancellationTokenSource cts = new CancellationTokenSource();
    private TState lastState;
    private TResult current;
    private …
Run Code Online (Sandbox Code Playgroud)

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

12
推荐指数
2
解决办法
1920
查看次数

在 Blazor 中,是否有一种方法可以撤消无效的用户输入而不更改状态?

在 Blazor 中,如何撤消无效的用户输入,而不更改组件的状态以触发重新渲染?

这是一个简单的 Blazor 计数器示例(在线尝试):

<label>Count:</label>
<button @onclick=Increment>@count times!</button><br>
A: <input @oninput=OnChange value="@count"><br>
B: <input @bind-value=count @bind-value:event="oninput">

@code {
    int count = 1;

    void Increment() => count++;

    void OnChange(ChangeEventArgs e)
    {
        var userValue = e.Value?.ToString(); 
        if (int.TryParse(userValue, out var v))
        {
            count = v;
        }
        else 
        {
            if (String.IsNullOrWhiteSpace(userValue))
            {
                count = 0;
            }

            // if count hasn't changed here,
            // I want to re-render "A"

            // this doesn't work
            e.Value = count.ToString();

            // this doesn't work …
Run Code Online (Sandbox Code Playgroud)

.net c# asp.net blazor blazor-webassembly

8
推荐指数
1
解决办法
2048
查看次数

Task.Yield 在 Blazor WebAssembly 中如何工作?

Mono/WASM 运行时(由 Blazor WebAssembly 使用)的Task.Yield底层如何工作?

澄清一下,我相信我对.NET Framework 和 .NET Core 的工作原理有很好的了解。Task.YieldMono 实现看起来并没有太大不同,简而言之,它可以归结为:

static Task Yield() 
{
    var tcs = new TaskCompletionSource<bool>();
    System.Threading.ThreadPool.QueueUserWorkItem(_ => tcs.TrySetResult(true));
    return tcs.Task;
}
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,这也适用于 Blazor WebAssembly(在线尝试):

<label>Tick Count: @tickCount</label><br>

@code 
{
    int tickCount = System.Environment.TickCount;

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender) CountAsync();
    }

    static Task Yield() 
    {
        var tcs = new TaskCompletionSource<bool>();
        System.Threading.ThreadPool.QueueUserWorkItem(_ => tcs.TrySetResult(true));
        return tcs.Task;
    }

    async void CountAsync() 
    {
        for (var …
Run Code Online (Sandbox Code Playgroud)

.net c# async-await webassembly blazor

8
推荐指数
1
解决办法
1588
查看次数

接受TCP客户端异步

我一直在制作服务器.我在方法中使用TcpListener.AcceptTcpClientAsync()async,但我不知道如何实际使它工作.我的代码现在是:

private static async void StartServer()
{
    Console.WriteLine("S: Server started on port {0}", WebVars.ServerPort);
    var listener = new TcpListener(WebVars.LocalIp, WebVars.ServerPort);
    listener.Start();
    var client = await listener.AcceptTcpClientAsync();
}
Run Code Online (Sandbox Code Playgroud)

我该如何处理客户?我只是继续编码,它会自动创建相同方法的新线程,还是我需要做一些魔术方法来为我做?

编辑:当前代码:

private static Task HandleClientAsync(TcpClient client)
{
    var stream = client.GetStream();
    // do stuff
}
/// <summary>
/// Method to be used on seperate thread.
/// </summary>
private static async void RunServerAsync()
{
    while (true)
    {
        Console.WriteLine("S: Server started on port {0}", WebVars.ServerPort);
        var listener = new TcpListener(WebVars.LocalIp, WebVars.ServerPort);
        listener.Start(); …
Run Code Online (Sandbox Code Playgroud)

c# tcp tcplistener tcpclient

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

在asp.net进程中运行多个并行任务的正确方法是什么?

我想我不懂东西.我原本以为Task.Yield()强制为一个任务启动一个新的线程/上下文,但是在重新阅读这个答案时,它似乎只是强制该方法是异步的.它仍然是在相同的背景下.

什么是正确的方法 - 在asp.net进程中 - 并行创建和运行多个任务而不会导致死锁?

换句话说,假设我有以下方法:

async Task createFileFromLongRunningComputation(int input) { 
    //many levels of async code
}
Run Code Online (Sandbox Code Playgroud)

当某个POST路由被命中时,我想同时启动上述方法3次,立即返回,但是当完成所有这三个时都要记录.

我想我需要把这样的东西放进我的行动中

public IHttpAction Post() {
   Task.WhenAll(
       createFileFromLongRunningComputation(1),
       createFileFromLongRunningComputation(2),
       createFileFromLongRunningComputation(3)
   ).ContinueWith((Task t) =>
      logger.Log("Computation completed")
   ).ConfigureAwait(false);
   return Ok();
Run Code Online (Sandbox Code Playgroud)

}

需要了解什么createFileFromLongRunningComputation?我原以为Task.Yield是正确的,但显然不是.

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

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

在循环内添加一个短延迟可防止它无限循环.为什么?

在使用.NET async/await API时,我遇到了好奇心:循环忽略了用作超时的延迟,直到我在循环内添加了一个短暂的延迟.这是如何运作的?不是最直观的行为!

完整计划:

using System;
using System.Threading.Tasks;

public class Program
{
    public static void Main(String[] args)
    {
        Task.Run(async () =>
        {
            await Task.WhenAny(Loop(), Task.Delay(TimeSpan.FromSeconds(1)));
            Console.WriteLine("Timed out!");
        })
        .Wait();
    }

    public static async Task Loop()
    {
        while(true)
        {
            // Commenting this out makes the code loop indefinitely!
            await Task.Delay(TimeSpan.FromMilliseconds(1));

            // This doesn't matter.
            await DoWork();
        }
    }

    public static async Task DoWork()
    {
        await Task.CompletedTask;
    }
}
Run Code Online (Sandbox Code Playgroud)

背景

实际的程序有,while(!done)但由于一个错误done从未设置为true.循环进行多次await调用.该Task.WhenAny呼叫是在单元测试中以防止Loop() …

c# asynchronous task infinite-loop async-await

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

等待和异步行为

鉴于这个例子:

void Main() { Test().Wait(); }

async Task Test()
{
    Console.WriteLine("Test A");
    await AsyncFunction();
    // It doesn't matter where the await is in AsyncFunction, it will always wait for the function to complete before executing the next line.
    Console.WriteLine("Test B");
}

async Task AsyncFunction()
{
    Console.WriteLine("AsyncFunction A");
    await Task.Yield();
    Console.WriteLine("AsyncFunction B");
}
Run Code Online (Sandbox Code Playgroud)

在任何情况下都不会在"AsyncFunction B"之前显示"Test B"

Test()中的await语句不是等待Task.Yield()完成恢复,而是整个AsyncFunction完成?

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

2
推荐指数
1
解决办法
96
查看次数