gpt4 book ai didi

c# - 在简单的自定义同步上下文中,异步、等待的线程峰值数量

转载 作者:太空宇宙 更新时间:2023-11-03 13:24:11 25 4
gpt4 key购买 nike

我写了一个简单的同步上下文,它什么都不做,只是将要在同一个线程上执行的任务排队,一次一个。

但是,看起来,当它遇到 await 时,它会启动一个新线程。没有。线程数翻了一番。我很难理解发生了什么。这不应该只运行 3 个线程(1 个线程用于应用程序,另外 2 个线程用于 GC、JIT)吗?

但它立即飙升至 6。

更新:在具有 2 个内核 - 4 个线程的 Intel Core i5 上运行 x64 Release Build。Microsoft .NET 4.5 SDK,已启用优化。

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
using System.Diagnostics;
using System.Threading;

class Program
{
static void Main(string[] args)
{
var ctx = new SyncContext();
SynchronizationContext.SetSynchronizationContext(ctx);

ctx.Post(o => Console.WriteLine("Hello"), null);

ctx.Post(
async o =>
{
Console.WriteLine("Entered async lambda.");
Console.ReadLine();
await Console.Out.WriteAsync("Async out.");
Console.WriteLine("Async post back.");
Console.ReadLine();
Console.WriteLine("End async.");
}, null);

ctx.Run();
}
}

public class SyncContext : SynchronizationContext
{
private readonly Queue<Action> messageQueue = new Queue<Action>();

private bool IsRunning { get; set; }

public void Stop()
{
IsRunning = false;
if (messageQueue.Count == 0)
{
lock (messageQueue)
{
Monitor.Pulse(messageQueue);
}
}
}

public void Run()
{
IsRunning = true;
Action queuedAction;

while (IsRunning)
{
lock (messageQueue)
{
if (messageQueue.Count == 0)
{
// Make sure it wasn't stopped while contending for the lock.
if (IsRunning)
{
Monitor.Wait(messageQueue);
}

if (!IsRunning)
{
break;
}
}

queuedAction = messageQueue.Dequeue();
}
queuedAction();
Console.WriteLine(Process.GetCurrentProcess().Threads.Count);

}
}

/// <summary>
/// When overridden in a derived class, dispatches an asynchronous message to a synchronization context.
/// </summary>
/// <param name="d">The <see cref="T:System.Threading.SendOrPostCallback" /> delegate to call.</param>
/// <param name="state">The object passed to the delegate.</param>
public override void Post(SendOrPostCallback d, object state)
{
lock (messageQueue)
{
messageQueue.Enqueue(() => d(state));
Monitor.Pulse(messageQueue);
}
}
}
}

输出:

Hello
3
Entered async lambda.

Async out.Async post back.

End async.
6

最佳答案

您看到的行为与同步上下文无关,如下面的代码所示。我认为原因是当您启动一个异步任务时,您正在使用 TPL 任务调度器。

最有可能的是,任务调度程序(或它背后的一些其他 TPL 惰性初始化逻辑)根据自己的需要旋转许多线程(或为此使用 ThreadPool 线程)。显然,这个逻辑足够聪明,不会对 synchronos 任务执行此操作,例如,如果您执行 await Task.FromResult(true) 而不是 await Console.Out .WriteAsync().

这是一个使用自定义等待程序说明这一点的示例:

using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApplication
{
class Program
{
static async Task TestAsync()
{
Console.WriteLine("A, threads: {0}, thread: {1}", Process.GetCurrentProcess().Threads.Count, Thread.CurrentThread.ManagedThreadId);
await new CustomAwaiter(async: false);
Console.WriteLine("B, threads: {0}, thread: {1}", Process.GetCurrentProcess().Threads.Count, Thread.CurrentThread.ManagedThreadId);

Console.WriteLine("C, threads: {0}, thread: {1}", Process.GetCurrentProcess().Threads.Count, Thread.CurrentThread.ManagedThreadId);
await new CustomAwaiter(async: true);
Console.WriteLine("D, threads: {0}, thread: {1}", Process.GetCurrentProcess().Threads.Count, Thread.CurrentThread.ManagedThreadId);
}

static void Main(string[] args)
{
TestAsync().Wait();
}
}

public struct CustomAwaiter:
System.Runtime.CompilerServices.INotifyCompletion
{
readonly bool _async;

public CustomAwaiter(bool async = true) { _async = async; }

// awaiter methods
public CustomAwaiter GetAwaiter() { return this; }

public bool IsCompleted {get { return !_async; } }

public void GetResult() { }

// ICriticalNotifyCompletion
public void OnCompleted(Action continuation) { continuation(); }
}
}

输出:

A, threads: 3, thread: 1B, threads: 3, thread: 1C, threads: 3, thread: 1D, threads: 6, thread: 1

正如@StephenCleary 所指出的,线程的数量实际上不是您应该在这里担心的问题。您也不应该依赖于这种行为。如果您对那里到底发生了什么感到好奇,请使用 .NET Reference Source 深入了解 TPL 实现细节。 .

关于c# - 在简单的自定义同步上下文中,异步、等待的线程峰值数量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23012279/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com