gpt4 book ai didi

C# 任务被取消

转载 作者:行者123 更新时间:2023-11-30 23:02:40 25 4
gpt4 key购买 nike

我写了一个静态类来测试用户的互联网连接,并在他们的连接状态发生变化时引发一个事件:

class InternetConnectionMonitor
{

public static EventHandler<EventArgs<bool>> StatusChanged;

private static bool isCancelled;
private static bool isConnected;

private static bool IsConnected
{
get
{
return isConnected;
}
set
{
if (isConnected != value)
{
StatusChanged(null, new EventArgs<bool>(value));
}
isConnected = value;
}
}

public static async void Start(TimeSpan interval)
{
//TODO Use a 1st party webpage for connectivity testing.
using (var client = new HttpClient())
{
client.Timeout = TimeSpan.FromSeconds(2);
while (!isCancelled)
{
try
{
await client.GetAsync("http://example.com");
IsConnected = true;
}
catch (Exception)
{
IsConnected = false;
}
await Task.Delay(interval);
}
}
}

public static void Stop()
{
isCancelled = true;
}
}

这个类工作得很好,但是,当在我的应用程序中使用 TPL 数据流进行一些其他处理时,在 Start() 方法的 while 循环中引发异常,表明任务已取消。我在这里发帖的原因是因为我从不取消任何任务。

这是我正在做的处理。 QueueTests 完成后,任务取消异常在 InternetConnectionMonitor 中引发,尽管 QueueTests 没有引用任何 InternetConnectionMonitor。

如果我不调用 validateProxies(),则永远不会引发异常。

private async void validateProxies(IEnumerable<Proxy> proxies)
{
validateProxiesButton.Enabled = false;
cancelValidatingProxiesButton.Enabled = true;
addProxiesButton.Enabled = false;
removeProxiesButton.Enabled = false;
proxyTester = new ProxyTester();
await proxyTester.QueueTests(proxies, judges);
validateProxiesButton.Enabled = true;
cancelValidatingProxiesButton.Enabled = false;
addProxiesButton.Enabled = true;
removeProxiesButton.Enabled = true;
MessageBox.Show("Complete!");
}

public class ProxyTester
{

private PauseOrCancelTokenSource pcts = new PauseOrCancelTokenSource();

public async Task QueueTests(IEnumerable<Proxy> proxies, IEnumerable<ProxyJudge> judges, int maxConcurrency = 100)
{
var testProxies = new ActionBlock<(Proxy proxy, IProxyTest test)>((tup) =>
{
tup.proxy.Status = ProxyStatus.Testing;
tup.proxy.Status = tup.proxy.TestValidity(tup.test);
}, new ExecutionDataflowBlockOptions { CancellationToken = pcts.Token.CancellationToken, MaxDegreeOfParallelism = maxConcurrency });

//Set each proxies status to Queued, and post to the dataflow block.
foreach (var proxy in proxies)
{
proxy.Status = ProxyStatus.Queued;
await testProxies.SendAsync((proxy, judges.GetRandomItem()));
}

testProxies.Complete();

try
{
await testProxies.Completion;
}
catch (Exception)
{

}
}

public void Cancel()
{
pcts.Cancel();
}

}

启动 InternetConnectionMonitor(JleruOHeP 在评论中要求)

public proxyTesterView()
{
InitializeComponent();

InternetConnectionMonitor.StatusChanged += InternetConnectionMonitor_StatusChanged;
InternetConnectionMonitor.Start(TimeSpan.FromSeconds(1));
}

private void InternetConnectionMonitor_StatusChanged(object sender, EventArgs<bool> e)
{
if (e.Value == true)
{
MessageBox.Show("Online");
}
else
{
MessageBox.Show("Offline");
}
}

最佳答案

解决了我自己的问题并想分享我的解决方案。经过一番思考,我感觉线程池线程在调用 QueueTests 时可能会耗尽,因为默认的最大并行度 (100) 很高。这种线程池耗尽似乎对 InternetConnectionMonitor 的 Start() 方法中对 client.GetAsync 的调用产生了意想不到的副作用,导致请求超时无法正确触发,从而导致 TaskCancelledException。

所以我生成了自己的显式线程并在其中同步执行测试。异常消失并按预期工作。

public static void Start()
{
//TODO Use a 1st party webpage for connectivity testing.
var t = new Thread(() =>
{
while (!isCancelled)
{
try
{
var req = HttpWebRequest.Create("http://example.com");
req.Timeout = 1000;
using (var resp = req.GetResponse())
{
resp.Close();
}
IsConnected = true;
}
catch (Exception ex)
{
IsConnected = false;
}
Console.WriteLine(IsConnected);
Thread.Sleep(1000);
}
});
t.Start();
}

关于C# 任务被取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50359991/

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