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();
}
}
我试图模仿一个启动无限while循环的模式,模拟网站的不断更新。我用模数模仿这个。从理论上讲,我希望这可以取消信号量排队的所有任务,并从头开始重新启动队列,但似乎并没有这样做。有人可以评论我的逻辑和模式吗?
现在的输出看起来像这样::
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
答案 0 :(得分:2)
所以,我有几个评论,一些是错误,一些只是建议:
update
是async void
,在事件处理程序之外几乎不会发生。你无法观察到错误,它可能会导致无数的错误。Task.WhenAll
startup
。这意味着当您取消10个站点更新中的5个时,您将启动50个新的站点更新。这是不必要的。CancellationToken
传递给SemaphoreSlim.WaitAsync
只会在等待信号量时观察到取消。任何已经运行的操作都不会停止。这真的是你的意图吗?更好的方法是在更新时检查令牌。这可以通过将令牌传递给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
分开,使其更加相似,在我看来,这是一个真实的情况,你有几个不同的操作(例如下载,解析,保存),你想查询之间的取消令牌那些步骤。