gpt4 book ai didi

c# - 任务排队

转载 作者:行者123 更新时间:2023-11-30 23:24:15 26 4
gpt4 key购买 nike

我有以下方法

public async Task<T> SomeMethod(parameters)
{
// here we execute some instructions which are not thread safe
}

我需要 SomeMethod 返回一个任务,以便其他方法可以异步运行(等待)它,而不是阻塞 UI 线程。

问题是 SomeMethod 可以并行调用,因为执行返回到 UI 线程,这会引发异常,因为 SomeMethod() 中的一些调用不是线程安全的。

确保对 SomeMethod 的所有调用都排队(并且可等待)并且该队列将按顺序执行的最佳方法是什么?

最佳答案

使用AsyncLock防止两个线程执行单个代码块:

(传统的 lock 将不起作用,因为您不能在其中使用 await 关键字)

private AsyncLock myAsyncLock = new AsyncLock();

public async Task<T> SomeMethod(parameters)
{
using (await myAsyncLock.LockAsync())
{
// here we execute some instructions which are not thread safe
}
}


public class AsyncLock
{
private readonly AsyncSemaphore m_semaphore;
private readonly Task<Releaser> m_releaser;

public AsyncLock()
{
m_semaphore = new AsyncSemaphore(1);
m_releaser = Task.FromResult(new Releaser(this));
}

public Task<Releaser> LockAsync()
{
var wait = m_semaphore.WaitAsync();
return wait.IsCompleted ?
m_releaser :
wait.ContinueWith((_, state) => new Releaser((AsyncLock)state),
this, System.Threading.CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
}

public struct Releaser : IDisposable
{
private readonly AsyncLock m_toRelease;

internal Releaser(AsyncLock toRelease) { m_toRelease = toRelease; }

public void Dispose()
{
if (m_toRelease != null)
m_toRelease.m_semaphore.Release();
}
}
}

// http://blogs.msdn.com/b/pfxteam/archive/2012/02/12/10266983.aspx
public class AsyncSemaphore
{
private readonly static Task s_completed = Task.FromResult(true);
private readonly Queue<TaskCompletionSource<bool>> m_waiters = new Queue<TaskCompletionSource<bool>>();
private int m_currentCount;

public AsyncSemaphore(int initialCount)
{
if (initialCount < 0) throw new ArgumentOutOfRangeException("initialCount");
m_currentCount = initialCount;
}

public Task WaitAsync()
{
lock (m_waiters)
{
if (m_currentCount > 0)
{
--m_currentCount;
return s_completed;
}
else
{
var waiter = new TaskCompletionSource<bool>();
m_waiters.Enqueue(waiter);
return waiter.Task;
}
}
}

public void Release()
{
TaskCompletionSource<bool> toRelease = null;
lock (m_waiters)
{
if (m_waiters.Count > 0)
toRelease = m_waiters.Dequeue();
else
++m_currentCount;
}
if (toRelease != null)
toRelease.SetResult(true);
}
}

关于c# - 任务<T>排队,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37880952/

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