Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/266.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
c#-wpf-Main UI在线程执行期间挂起_C#_Wpf_Multithreading - Fatal编程技术网

c#-wpf-Main UI在线程执行期间挂起

c#-wpf-Main UI在线程执行期间挂起,c#,wpf,multithreading,C#,Wpf,Multithreading,我正在使用多线程WPF。问题是在主线程挂起的执行过程中,就像它在主UI中等待某个东西或无限循环一样。我不知道在WPF中使用多线程时是否还有其他方法。请参见下面的我的代码: Thread myNewThread1 = new Thread(() => ping(IP1, img_m)); Thread myNewThread2 = new Thread(() => ping(IP2, img_h)); Thread myNewThread3 = new Thread(() =>

我正在使用多线程WPF。问题是在主线程挂起的执行过程中,就像它在主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);
}    

不要在dispatcher中包含对p.Send方法的调用-当前只有Thread.Sleep(500)在后台完成,其他所有操作都在UI线程中完成


此外,我相信由于Thread.Sleep函数,UI线程永远不会有机会工作,因此不会出现ping。使用Thread.Sleep替换Thread.Timer对象。

您的主线程由于
调度程序而挂起。调用
错误用法,它应该仅用于UI逻辑,因此您应该将面向
Ping的逻辑移出它

不要为此使用
BackgroundWorker
,这是一个过时且繁重的构造,您并不真正需要它。另外,不要使用线程进行ping,这是错误的方法,这就是为什么:

ping操作是与网络相关的,而用于等待远程服务器响应的线程只会浪费系统资源,因为它除了等待之外什么都没有。因此,您应该切换到异步方法

您应该订阅事件并调用方法,如下所示:

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
功能,该功能正是针对此类情况引入的(代码部分来自:

//异步事件处理程序
私有异步无效btn_单击(对象发送方,事件参数e)
{
//对所有IP的异步调用
var results=await PingAsync(新列表{IP1,IP2,IP3,IP4,IP5});
//这里我们不需要Dispatcher,因为Wait将为您恢复UI上下文
PingCompleted(结果[0],img_m);
//等
}
私有void ping已完成(pingr,MediaTypeNames.Image img)
{
字符串地址;
if(r.Status==IPStatus.Success)
{
imageAddress=“subonline.gif”;
}
其他的
{
imageAddress=“suboffline.gif”;
}
var image=新的位图图像();
image.BeginInit();
image.UriSource=新Uri(imageAddress,UriKind.Relative);
image.CacheOption=BitmapCacheOption.OnLoad;
image.EndInit();
设置动画源(img,image);
}
//辅助方法
专用异步任务PingAsync(列出列表)
{
Ping pingSender=新Ping();
var tasks=theListOfIPs.Select(ip=>pingSender.SendPingAsync(ip,1000,新字节[5]);
返回等待任务。WhenAll(任务);
}

使用
BackgroundWorker
而不是使用线程(或任何其他自制的后台处理),最好看看PingAsync和PingCompleted。大家好,谢谢你们的回复,我现在切换到BackgroundWorker,它的工作很好:)@NikhilAgrawal
BackgroundWorker
是非常过时的方法,你们应该避免它。
// 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);
}