![](/img/trans.png)
[英]After passing variable to async method, how will setting variable to new instance in main thread affect async method?
[英]How avoid async method to use new thread?
我读过await / async不应创建/使用新线程,但编译器会在后台创建astate machien。...所以我尝试了此操作,每次对F1的调用都使用ThreadPool中的线程。
class Program
{
static System.Threading.SemaphoreSlim sem =
new System.Threading.SemaphoreSlim(20, 20);
static async void F1()
{
await sem.WaitAsync();
await sem.WaitAsync();
await Task.Delay(6000);
var threadId = GetCurrentThreadId();
sem.Release();
sem.Release();
}
static void Main(string[] args)
{
var threadId = GetCurrentThreadId();
F1();
F1();
F1();
F1();
F1();
F1();
F1();
F1();
Task.Delay(30000).Wait();
}
[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();
}
您已经使用了await Task.Delay(6000)
,它保证不会同步完成,因此:完成将通过任何可能的方式(通常是线程池)返回(因为此处没有同步上下文)。 只要您不长时间捆绑线程池线程,它就很便宜。 如果所做的只是捕获当前线程ID并释放,则它们实际上应该在启动后立即完成。
代码需要在某个地方运行; 您希望它在哪个线程上运行? 您的主线程当前处于阻塞的Wait()
调用中,因此它无法执行任何操作。 注意:您几乎永远不要在不完整的Task
上调用.Wait()
。
经过一番研究,我找到了想要的答案。 https://blogs.msdn.microsoft.com/pfxteam/2012/01/20/await-synchronizationcontext-and-console-apps/
实际上Mrinal Kamboj在我的问题上添加了一条评论,指出了正确的方向。 我需要为继续运行创建一个同步上下文 。 此代码段还显示了为什么您不应该对未完成的任务使用Wait():如果继续在同一线程上运行(对于GUI线程或ASP.NET发生),如果该线程被锁定以等待继续,那么我们将在死机中运行-锁定情况。
class Program
{
static System.Threading.SemaphoreSlim Semaphore = new System.Threading.SemaphoreSlim(3, 3);
static async Task F(int i)
{
Console.WriteLine($"F{i} starts on " + GetCurrentThreadId());
await Semaphore.WaitAsync();
Console.WriteLine($"F{i} continues on " + GetCurrentThreadId());
await Task.Delay(6000); //.ConfigureAwait(false); //<- uncomment to solve deadlock
Console.WriteLine($"F{i} ends on " + GetCurrentThreadId());
Semaphore.Release(1);
//DeadLock();
}
static void DeadLock()
{
F(70).Wait();
}
static void Main(string[] args)
{
var context = new SingleThreadSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(context);
for (int i = 0; i < 10; i++)
{
int ind = i;
F(ind);
}
context.RunOnCurrentThread();
}
[DllImport("kernel32.dll")]
static extern uint GetCurrentThreadId();
}
sealed class SingleThreadSynchronizationContext : SynchronizationContext
{
private readonly Thread Thread = Thread.CurrentThread;
public override void Post(SendOrPostCallback d, object state)
{
if (d == null)
throw new ArgumentNullException("d");
WorkItemsQueue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
}
public override void Send(SendOrPostCallback d, object state)
{
throw new NotSupportedException("Synchronously sending is not supported.");
}
public void RunOnCurrentThread()
{
foreach (var workItem in WorkItemsQueue.GetConsumingEnumerable())
workItem.Key(workItem.Value);
}
public void Complete() { WorkItemsQueue.CompleteAdding(); }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.