gpt4 book ai didi

c# - SemaphoreSlim 取消 token

转载 作者:太空狗 更新时间:2023-10-29 21:50:13 25 4
gpt4 key购买 nike

class Program
{
static IEnumerable<site> list = Enumerable.Range(1, 10).Select(i => new site(i.ToString()));

static void Main(string[] args)
{
startup();
Console.ReadKey();
}

static public void startup()
{
router.cts = new CancellationTokenSource();

foreach (var s in list)
{
update(s);
}
}

async static public void update(site s)
{
try
{
while (true)
{
await s.Refresh();
if (site.count % 4 == 0)
{
Console.WriteLine("Reseting Queue");
router.cts.Cancel();
}
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled");
startup();
}
}
}

class router
{
public static SemaphoreSlim ss = new SemaphoreSlim(1);
public static CancellationTokenSource cts { get; set; }


}

class site
{
public static int count = 0;
public string sitename {get; set;}

public site(string s)
{
sitename = s;
}

async public Task Refresh()
{
await router.ss.WaitAsync(router.cts.Token);
//Console.WriteLine("{0}:: Start Refreshing ", sitename);
await Task.Delay(1000);

Console.WriteLine("{0}:: Done Refreshing ", sitename);
count++;
router.ss.Release();
}


}

我正在尝试模仿一种启动无限循环的模式,该循环模拟网站的持续更新。我正在用模数模仿这个。从理论上讲,我希望这样可以取消信号量排队的所有任务并从头开始重新启动队列,但它似乎并没有这样做。有人可以评论我的逻辑和模式吗?

现在的输出看起来像这样::

1:: Done Refreshing
2:: Done Refreshing
3:: Done Refreshing
4:: Done Refreshing
Reseting Queue
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
5:: Done Refreshing
1:: Done Refreshing
2:: Done Refreshing
3:: Done Refreshing
Reseting Queue
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
4:: Done Refreshing
5:: Done Refreshing
6:: Done Refreshing
7:: Done Refreshing
Reseting Queue
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
Canceled
8:: Done Refreshing
9:: Done Refreshing
10:: Done Refreshing
1:: Done Refreshing
Reseting Queue
Canceled

最佳答案

所以,我有几条评论,有些是错误,有些只是建议:

  1. 如果可以的话,我更喜欢检查取消和结束操作,而不是抛出异常。
  2. updateasync void,这是在事件处理程序之外几乎不应该发生的事情。您无法观察到错误,它可能会导致无数错误。
  3. 要并行进行网站更新,触发所有更新并只等待一次 Task.WhenAll
  4. 当任何操作被取消时,您正在调用 startup。这意味着当您取消 10 个网站更新中的 5 个时,您将启动 50 个新的网站更新。这是不必要的。
  5. CancellationToken 传递给 SemaphoreSlim.WaitAsync 只会在等待信号量时观察到取消。任何已经在运行的操作都不会停止。这真的是你的意图吗?更好的方法是在更新时检查 token 。这可以通过将 token 传递给 Task.Delay 来模拟。操作。

这是我的做法:

class Program
{
static IEnumerable<site> list = Enumerable.Range(1, 10).Select(i => new site(i.ToString()));

static void Main(string[] args)
{
Startup().Wait();
Console.ReadKey();
}

static async Task Startup()
{
while (true)
{
router.cts = new CancellationTokenSource();

await Task.WhenAll(list.Select(s => Update(s)));
}
}

static Task Update(site s)
{
if (site.count % 4 == 0)
{
Console.WriteLine("Reseting Queue");
router.cts.Cancel();
}
else
{
return s.Refresh();
}
}
}

class router
{
public static SemaphoreSlim ss = new SemaphoreSlim(1);
public static CancellationTokenSource cts { get; set; }
}

class site
{
public static int count = 0;
public string sitename {get; set;}

public site(string s)
{
sitename = s;
}

public async Task Refresh()
{
await router.ss.WaitAsync();
try
{
if (router.cts.token.IsCancellationRequested)
{
return;
}
await Task.Delay(500);

if (router.cts.token.IsCancellationRequested)
{
return;
}
await Task.Delay(500);

Console.WriteLine("{0}:: Done Refreshing ", sitename);
count++;
}
finally
{
router.ss.Release();
}
}
}

在我看来,我拆分了 Task.Delay 以使其更类似于您有多个不同操作(例如下载、解析、保存)并且您想要查询这些步骤之间的取消 token 。

关于c# - SemaphoreSlim 取消 token ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24092416/

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