C# 如何在 BackGroundWorker 中停止 Ping / 在函数之外停止发送异步
本文关键字:异步 函数 BackGroundWorker Ping | 更新日期: 2023-09-27 18:30:27
所以我有一个看起来像这样的BW:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
if ((worker.CancellationPending == true))
{
e.Cancel = true;
return;
}
else
{
worker.ReportProgress(1);
e.Result = PCIsOnline((string)e.Argument);
}
}
PCIsOnline 功能启动 Ping.Send。一切正常。但在某些情况下,我想停止 BW(或停止 ping)。
我试过这个:
BW。取消异步();- 但这对我没有帮助,因为APP永远不会再回到bw_DoWork停止。所以我有一种方法可以停止ping或bw。所以我可以重新开始。
顺便说一句,出于某种原因,这也无济于事。
bw.CancelAsync();
while (!bw.IsBusy)
{
System.Threading.Thread.Sleep(50);
}
因为它只是永远循环。我想这是因为我睡眠线程,但它是一个主线程,尽管 BW 线程不应该停止。但似乎确实如此。我见过一个线程,其中使用了睡眠 DoEvents 而不是睡眠,但我使用的是 WPF 并且它没有它。而且我真的不想等待ping来完成它的工作。
我已经阅读了很多关于 BW 以及如何停止的帖子,但没有一个对我有帮助。Coz 当我发送 CancelAsync() DoWork 时,一切都准备好了取消待处理检查,永远不会回到那里。
PS:第一次时间我开始 BW 甚至TextBox_FocusLost。并希望在List_SelectChanged中再次停止并运行它。
添加:
public static bool PCIsOnline(string arg)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 2;
try
{
PingReply reply = pingSender.Send(arg, timeout, buffer, options);
if (reply.Status == IPStatus.Success) { return true; }
else { return false; }
}
catch
{
return false;
}
}
新增2:正如之前在评论中所说,与其使用 BW,不如使用 SendAsync。我的代码现在看起来像这样。但我仍然不明白如何在PCIsOnline功能之外停止SendAsync。
public static void PCIsOnline(string arg)
{
Ping pingSender = new Ping();
pingSender.PingCompleted += new PingCompletedEventHandler(PingCompletedCallback);
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 2;
pingSender.SendAsync(arg, timeout, buffer, options);
}
private static void PingCompletedCallback(object sender, PingCompletedEventArgs e)
{
if (e.Cancelled)
{
Console.WriteLine("Ping canceled.");
}
if (e.Error != null)
{
Console.WriteLine("Ping failed:");
Console.WriteLine(e.Error.ToString());
}
PingReply reply = e.Reply;
HandleReply(reply);
}
所以我仍然在寻找一种方法来中断 BW 并重新启动它或停止 PingAsync。
问题是你只向 bw 发送取消。但是您还需要向Ping(SendAsync)发送取消。
发送取消到平
Ping.SendAsyncCancel();
bw.CancelAsync();
使用发送异步:
public static bool PCIsOnline(string arg)
{
Ping pingSender = new Ping();
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 2;
try
{
PingReply reply = pingSender.SendAsync(arg, timeout, buffer, options);
if (reply.Status == IPStatus.Success) { return true; }
else { return false; }
}
catch
{
return false;
}
}
由于我找不到停止ping的方法,因此如果不是我需要的ATM结果,我决定忽略ping结果。所以我只是将签入添加到 HandleReply 中,如果不再需要此 ping 结果,则发送返回。
private void Name_LostFocus(object sender, System.EventArgs e)
{
var textBox = sender as TextBox;
//No longer Using BW since Ping.SendAsync() does the job
PCIsOnline(textBox.Text);
}
private void Search_SelectChanged(object sender, SelectionChangedEventArgs e)
{
ListBox Search = sender as ListBox;
if (Search.SelectedValue != null)
{
this.OldName.Text = Search.SelectedValue.ToString();
PCIsOnline(this.OldName.Text);
}
}
public void PCIsOnline(string arg)
{
Ping pingSender = new Ping();
//Sending argument to perform check later
pingSender.PingCompleted += (sender1, args) => PingCompletedCallback(sender1, args, arg);
PingOptions options = new PingOptions();
options.DontFragment = true;
string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
byte[] buffer = Encoding.ASCII.GetBytes(data);
int timeout = 5;
pbrTest.Visibility = System.Windows.Visibility.Visible;
pingSender.SendAsync(arg, timeout, buffer, options);
}
private void PingCompletedCallback(object sender, PingCompletedEventArgs e, String Current)
{
if (e.Cancelled)
{
HandleReply(null, Current, "Cancelled");
return;
}
if (e.Error != null)
{
HandleReply(null, Current, "Error");
return;
}
PingReply reply = e.Reply;
HandleReply(reply, Current, "");
}
private void HandleReply(PingReply reply, String PC, String msgtype = "")
{
//Ignore old result I only need one that is in OldName textBox
if (PC != this.OldName.Text) { return; }
//Next you should add your result handling
//Happens on a error
if (reply == null)
{
/*do something*/
}
//PC is online
else if (reply.Status == IPStatus.Success)
{
/*do something*/
}
//PC is offline
else
{
/*do something*/
}
}
不是解决问题的最好方法,但这是我能想到的最好的方法。