xamarin C# WhenAll(任务)使应用程序崩溃,没有任何异常或错误

wj8zmpe1  于 2022-12-25  发布在  C#
关注(0)|答案(1)|浏览(201)

这个问题的简要总结是,我目前正在尝试在Xamarin中创建一个应用程序,该应用程序可以找到所连接PC的IP地址(使用SMB 2)。使用await Dns.GetHostAddressesAsync(Dns.GetHostName())可以获得正确IP地址的前三段。从这里,我ping了从0到255的所有地址(例如xxx.xxx.xxx.0 -〉xxx.xxx.xxx.255),看看是否得到响应。
ping会为每个IP地址创建一个新的任务(比如255),最后它会执行WhenAll(task),这就是崩溃发生的地方。奇怪的是它不是每次都崩溃,而是每运行3-5次。
ping方法:

async Task PingAsyncCustom (List<String> testIPs)
        {
                if (Battery.PowerSource == BatteryPowerSource.Usb)
                {
                    List<Task> tasks = new List<Task>();
                    
                    foreach (string ips in testIPs) 
                    {
                        using (Ping ping = new Ping())
                        {
                            var taskPing = InitiatePing(ips, ping);
                            tasks.Add(taskPing);
                        }
                    }
                    try
                    {
                        await Task.WhenAll(tasks);
                    }
                    catch (Exception e)
                    {
                        Crashes.TrackError(e);
                        Analytics.TrackEvent("WhenAll Crash" + e.ToString());
                    }
                    Report("Waiting Finished");
                    tasks.RemoveAll(x => x.IsCompleted);
                    Report("Ping Async Finished");
                }
                else
                {
                    Report("Disconected during Ping Sweep");
                    pIps.Clear();
                }
            
        }

initiatePing方法:

private async Task InitiatePing (String ip, Ping ping)
        {
            var tcs = new TaskCompletionSource<PingReply>();
            var options = new PingOptions(64,true); 
            string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
            byte[] buffer = Encoding.ASCII.GetBytes(data);
            try
            {
                Report("InitiatePing: " + ip);
                var reply = await ping.SendPingAsync(ip, 2000, buffer, options);
                if (reply.Status == IPStatus.Success)
                {
                    lock (lockObj)
                    {
                        pIps.Add(reply);
                    }
                }
            }
            catch(PingException e)
            {
                Report("PingException: " + e.ToString());
            }

        }

输出中的另一个问题是,它似乎创建了太多的线程&有时,并不总是,它会显示一个致命的错误:(我的一次跑步的片段)

Thread started: <Thread Pool> #99
Thread started: <Thread Pool> #100
Thread started: <Thread Pool> #101
Thread started: <Thread Pool> #102
Thread started: <Thread Pool> #103
Thread started: <Thread Pool> #104
Thread started: <Thread Pool> #105
Thread started: <Thread Pool> #106
Thread started: <Thread Pool> #107
[libc] Fatal signal 7 (SIGBUS), code 1 (BUS_ADRALN), fault addr

如果有更好的方法来实现这一点,我会很乐意接受你的建议。如果没有,那么也许闪耀一些光到底是什么问题和一些解决方案将非常赞赏。
“以前的代码更改:“最初它在WhenAll(task)中没有任何try & catch,所以我添加了它,但它似乎仍然崩溃。还尝试在完成后删除列表。此外,在创建新的Ping()时,我使用using在完成后正确处理。

rkttyhzu

rkttyhzu1#

作为一种解决方法,我可以在list<task>上创建一个限制,这样它就不会在254个地址上执行Task.WhenAll
代码如下:

async Task PingAsyncCustom (List<String> testIPs)
    {
            if (Battery.PowerSource == BatteryPowerSource.Usb)
            {
                var tasks = new List<Task>();
                
                foreach (string ips in testIPs) 
                {
                    if (Battery.PowerSource == BatteryPowerSource.Usb)
                    {
                        var taskPing = InitiatePing(ips);
                        tasks.Add(taskPing);
                        if (tasks.Count() == 10)
                    {
                        try
                        {
                            await Task.WhenAll(tasks);
                            tasks.Clear();
                        }
                        catch (Exception e)
                        {
                            Analytics.TrackEvent("Whenall10 Crash" + e.ToString());
                        }
                    }
                    }
                    else
                    {
                        pIps.Clear();
                        break;
                    }
                }
            try
            {
                await Task.WhenAll(tasks);
            }
            catch (Exception e)
            {
                Crashes.TrackError(e);
                Analytics.TrackEvent("WhenAll Crash" + e.ToString());
            }
                tasks.Clear();
            }
            else
            {
                pIps.Clear();
            }
        
    }

现在我使用tasks.count() == 10,但是我能想到的一个改进是删除已经完成的任务并用新任务替换它们。目前它将等待所有10个任务完成,然后跳到下一批10个任务。

相关问题