我正在使用带多线程的WPF。问题是在执行MAIN线程挂起期间,就像在主UI中等待某些东西或无限循环一样。在WPF中涉及多线程时,我不知道是否还有其他方法。请参阅下面的代码:
Thread myNewThread1 = new Thread(() => ping(IP1, img_m));
Thread myNewThread2 = new Thread(() => ping(IP2, img_h));
Thread myNewThread3 = new Thread(() => ping(IP3, img_c));
Thread myNewThread4 = new Thread(() => ping(IP4, img_b));
Thread myNewThread5 = new Thread(() => ping(IP5, img_e));
myNewThread1.Start();
myNewThread2.Start();
myNewThread3.Start();
myNewThread4.Start();
myNewThread5.Start();
private void ping(string IP, Image img)
{
this.Dispatcher.Invoke(() =>
{
Ping p = new Ping();
var r = p.Send(IP, 1000, new byte[5]);
if (r.Status == IPStatus.Success)
{
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri("subonline.gif", UriKind.Relative);
image.CacheOption = BitmapCacheOption.OnLoad;
image.EndInit();
ImageBehavior.SetAnimatedSource(img, image);
}
else
{
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri("suboffline.gif", UriKind.Relative);
image.CacheOption = BitmapCacheOption.OnLoad;
image.EndInit();
ImageBehavior.SetAnimatedSource(img, image);
}
});
Thread.Sleep(500);
ping(IP, img);
}
答案 0 :(得分:1)
您的主线程由于Dispatcher.Invoke
错误使用而挂起,它应仅用于UI逻辑,因此您应该移出面向Ping
的逻辑。
不要使用BackgroundWorker
,这是一个你真正不需要的过时和沉重的结构。另外,不要用于ping的线程,这是错误的方法,这就是原因:
Ping操作与网络相关,您用于等待远程服务器响应的线程只会浪费系统资源,因为它绝对没有除了等待。所以你应该为此切换到异步方法。
您应该订阅Ping.PingCompleted
事件并调用SendAsync
方法,如下所示:
private void ping(string IP, MediaTypeNames.Image img)
{
Ping p = new Ping();
PingReply r;
// lambda delegate here, may use event handler instead
p.PingCompleted += (sender, args) => { PingCompleted(args, img); };
r = p.SendAsync(IP, 1000, new byte[5], null);
}
private void PingCompleted(PingCompletedEventArgs args, MediaTypeNames.Image img)
{
this.Dispatcher.Invoke(() =>
{
string imageAddress;
if (args.Reply.Status == IPStatus.Success)
{
imageAddress = "subonline.gif";
}
else
{
imageAddress = "suboffline.gif";
}
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(imageAddress, UriKind.Relative);
image.CacheOption = BitmapCacheOption.OnLoad;
image.EndInit();
ImageBehavior.SetAnimatedSource(img, image);
});
}
或者您应该使用async/await
功能,该功能是针对此类情况引入的(代码部分来自this answer):
// async event handler
private async void btn_Click(object sender, EventArgs e)
{
// async call to all the ips
var results = await PingAsync(new List<string> { IP1, IP2, IP3, IP4, IP5 });
// here we do not need the Dispatcher as await will restore UI context for you
PingCompleted(results[0], img_m);
// etc
}
private void PingCompleted(PingReply r, MediaTypeNames.Image img)
{
string imageAddress;
if (r.Status == IPStatus.Success)
{
imageAddress = "subonline.gif";
}
else
{
imageAddress = "suboffline.gif";
}
var image = new BitmapImage();
image.BeginInit();
image.UriSource = new Uri(imageAddress, UriKind.Relative);
image.CacheOption = BitmapCacheOption.OnLoad;
image.EndInit();
ImageBehavior.SetAnimatedSource(img, image);
}
// helper method
private async Task<PingReply[]> PingAsync(List<string> theListOfIPs)
{
Ping pingSender = new Ping();
var tasks = theListOfIPs.Select(ip => pingSender.SendPingAsync(ip, 1000, new byte[5]));
return await Task.WhenAll(tasks);
}
答案 1 :(得分:0)
不要在调度程序中包含对p.Send方法的调用 - 当前只有Thread.Sleep(500)在后台完成,其他所有操作都在UI线程中完成。
另外,我相信由于Thread.Sleep,函数永远不会给UI线程一个工作的机会,所以ping不会发生。将Thread.Sleep替换为Thread.Timer对象。