WPF 应用程序运行并行操作

问题描述 投票:0回答:1

我正在开发一个小型软件应用程序。其工作原理的总体逻辑是这样的。

  1. UDP 字符串正在本地网络上广播
  2. 应用程序会在后台捕获该字符串,并根据该字符串的内容,触发一些简单的操作(更新本地数据库 - 将文件从a复制到b)

现在我使用此方法在后台启动监听,并且在此过程中我仍然可以使用我的应用程序。

public async Task StartListeningAsync()
{
    Debug.WriteLine("UDP LISTENER IS ACTIVE");
    udpClient = new UdpClient(udpPort);

    try
    {
        while (true)
        {
            UdpReceiveResult result = await udpClient.ReceiveAsync();
            string receivedString = Encoding.UTF8.GetString(result.Buffer);
            OnUdpMessageReceived(receivedString);
        }
    }
    catch (Exception ex)
    {
        Debug.WriteLine($"Error in UDP listener: {ex.Message}");
    }
    finally
    {
        udpClient.Close();
    }
}

我的问题是: 要触发我在第 2 点中解释的操作,我应该遵循什么是允许我在这些任务运行时使用应用程序的最佳方法。

现在我使用在应用程序启动时初始化的事件处理程序:

private async void UdpMessageReceivedHandler(object sender, UdpMessageEventArgs e)
{
    string receivedMessage = e.Message;

    // Handle the received message (e.g., trigger specific actions)
    if (receivedMessage.StartsWith("A"))
    {
        // Trigger Action A
        Debug.WriteLine("Action A triggered!");
        // Implement your action logic here
        string sourceDirectory = @"C:\Users\0031181\OneDrive - DEME\Documents\1-Office\IT@G-tec\SAC\apps\seismic\sgy\dataset";
        string destinationDirectory = @"C:\Users\0031181\OneDrive - DEME\Documents\1-Office\IT@G-tec\SAC\apps\seismic\sgy\dataset\dataset2";

        await Task.Run(() => CopyFiles(sourceDirectory, destinationDirectory));
    }
    else if (receivedMessage.StartsWith("B"))
    {
        // Trigger Action B
        Debug.WriteLine("Action B triggered!");
        // Implement your action logic here
    }
}

问题是我知道 Task.Run 可能会触发一个从未完成的任务,我担心这可能会导致错误。

这种方法正确还是有更优雅的方法来实现我的目标?

c# wpf async-await concurrency
1个回答
1
投票

问题是我知道 Task.Run 可能会触发一个从未完成的任务,我担心这可能会导致错误。

这段代码的一个明显问题是缺乏任何异常处理。通过将

UdpMessageReceivedHandler
中的所有内容放入 try-catch 并处理任何异常,可以很容易地处理此问题。如何处理它们取决于你,向 UI 线程发布消息?记录失败?就让应用程序崩溃吗?

您也可以直接从接收线程调用消息处理程序,例如:

string receivedString = Encoding.UTF8.GetString(result.Buffer);
await UdpMessageReceivedHandler(receivedString);

...
private async Task UdpMessageReceivedHandler(string receivedString){
...

但请注意,这将序列化所有工作,因此如果花费的时间比发送消息的速率更长,您将遇到问题。使用此模型,任何异常都会流向称为

StartListeningAsync
的内容,因此它可以处理它们。

另一种选择是将所有收到的消息放入队列中(如 BlockingCollection),并使用单独的任务来处理队列中的消息。这应该允许您检查队列处理任务是否因失败而提前完成并处理它。 Dataflow 是设置队列管道进行处理的一种方法,但还有许多其他选项。 DataFlow 的一个好处是它非常灵活,因此并行处理消息非常容易。

还要考虑 UDP 是否确实适合您的应用程序。没有内置的可靠性,因此您应该预料到数据包会丢失。我会考虑一些可以传递 messages 的库,例如 http、gRPC、MQTT 或任何其他协议。

© www.soinside.com 2019 - 2024. All rights reserved.