gpt4 book ai didi

c# - 如何确保部分代码(包含异步)只被调用一次?

转载 作者:太空狗 更新时间:2023-10-29 19:57:07 25 4
gpt4 key购买 nike

所以,我有一个方法,其中包含对服务器的异步调用。该代码是从 3rd 方工具调用的,它有时会以某种方式从不同的线程连续多次调用相同的方法,所以我不能影响它。

我想确定的是我的方法被调用一次,然后,其他调用应该被忽略。

起初,我尝试用 bool isBusy 来锁定(locker),但这并不令我满意,因为异步请求仍然从第二个线程调用了几次,它的速度足以看到 isBusy=true;

然后,我尝试了 Monitor

                object obj = new object();
Monitor.TryEnter(obj);
try
{

var res = await _dataService.RequestServerAsync(SelectedIndex, e.StartIndex, e.Count);

****
}
finally
{
Monitor.Exit(obj);
}

但是,在 Exit() 上,我遇到了异常:

A first chance exception of type 'System.Threading.SynchronizationLockException'

有没有其他方法可以保证代码只执行1次?

最佳答案

放入类:

private int entered = 0;

在方法中:

if (Interlocked.Increment(ref entered) != 1)
{
return;
}

只有第一次调用该方法才能将 entered 从 0 更改为 1。其他方法会将其变为 2、3、4、5...

很明显,如果您希望您的方法可以重新触发,您需要一些东西来重置 entered...

Interlocked.Exchange(ref entered, 0);

在成功调用方法结束时。

啊...并且不可能在 await 周围使用 lock/Monitor.*,因为当前线程该方法可以更改,而几乎所有同步库都希望您用来进入锁的线程与您用来退出锁的线程相同。

您甚至可以使用 Interlocked.CompareExchange()...

if (Interlocked.CompareExchange(ref entered, 1, 0) != 0)
{
return;
}

第一个进入的线程将能够将 entered 的值从 0 交换为 1,它会收到旧值 0(因此 if 失败并继续执行剩余代码)。其他线程将使 CompareExchange 失败并看到“当前”值 1,因此进入 if 并退出该方法

关于c# - 如何确保部分代码(包含异步)只被调用一次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18333580/

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