簡體   English   中英

c# WPF Window 在 While 循環期間不顯示。 UDP

[英]c# WPF Window doesn't show during While Loop. UDP

我是 C# 的新手,正在嘗試使用 UDP 閱讀器。 我每秒都在發送連續的“測試”短信。 但是主 Window 和 tex 框根本沒有出現。 我注意到當我引入一個while循環時總是會發生這種情況。 如果沒有 while 循環,窗口/文本框會出現並寫入一次傳入消息“文本”。 我有一個單獨的程序不斷發送 UDP 消息。

我被困在這里。 帶有 while 循環的代碼在控制台中可以正常工作。

namespace WpfApp2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            bool done = false;
            var receivePort = 11000;

            InitializeComponent();

            UdpClient readerClient = new UdpClient(receivePort);


            while (!done)
            {

                var remoteEP = new IPEndPoint(IPAddress.Any, receivePort);

                byte[] bytesReceived = readerClient.Receive(ref remoteEP);

                tb.AppendText(Encoding.ASCII.GetString(bytesReceived));

            }
        }
    }
}

重繪控件的更新是通過消息完成的。 必須處理這些消息(它發生在后台)。 您面臨的問題是由於 while 循環而未處理這些消息。 whileloop/Receive 阻塞當前線程。

您應該做的最好的事情是將 UDP 代碼移動到單獨的線程/任務中。

你可以試試這樣的。

這是一個使用單獨線程的示例:

public partial class MainWindow : Window
{
    private UdpClient _readerClient;
    private Thread _udpThread;
    private ManualResetEvent _done = new ManualResetEvent(false);
    private int _receivePort;

    public MainWindow()
    {
        _receivePort = 11000;

        InitializeComponent();

        _readerClient = new UdpClient(_receivePort);

        _udpThread = new Thread(UDPHandler);
    }


    private void UDPHandler()
    {

        while (!_done.WaitOne(0))
        {

            var remoteEP = new IPEndPoint(IPAddress.Any, _receivePort);

            byte[] bytesReceived = _readerClient.Receive(ref remoteEP);

            // since this is (probably) NOT the UI thread, post it to it's dispatcher. (WPF)
            // this makes multithreading harder...
            tb.Dispatcher.BeginInvoke(new Action(() =>
            {
                tb.AppendText(Encoding.ASCII.GetString(bytesReceived));
            }));

        }
    }

    private void Window_Closed(object sender, EventArgs e)
    {
        // stop the while loop
        _done.Set();
        // wait until the thread finished.
        _udpThread.Join();
    }
}

您應該添加一些異常處理等。這只是一個例子..

您的問題是,您正在使用並阻塞 WPF 想要用於繪制其元素的主線程。

所以 WPF 必須等到你的循環完成。

C# 提供的是異步/等待(未經測試)

namespace WpfApp2
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        // async Task is important here
        public async Task DoStuffAsync()
        {
            bool done = false;
            var receivePort = 11000;
            
            UdpClient readerClient = new UdpClient(receivePort);
            var remoteEP = new IPEndPoint(IPAddress.Any, receivePort);
            readerClient.Connect(remoteEP);

            while (!done)
            {
                // Here we await the result
                // meanwhile the main thread is not blocked and WPF can do its work
                // look for ...Async functions in your modules that provide awaitable functionality
                byte[] bytesReceived = await readerClient.ReceiveAsync();

                tb.AppendText(Encoding.ASCII.GetString(bytesReceived));

            }
        }
        
        public MainWindow()
        {
            InitializeComponent();

            // Here we call an async function.
            // Problem here: You cannot catch exceptions, because of asyncs nature
            // But you can set code that is executed when the async function fails
            DoStuffAsync().ContinueWith(t =>
            {
                // Exception is in t.Exception
            }, TaskContinuationOptions.OnlyOnFaulted);
        }
    }
}

注意:此示例旨在進行盡可能少的更改,而不是最佳實踐。

謝謝您的意見。 我仍然努力讓這個工作,但不得不學習很多。 我不確定這是否是最佳實踐代碼,但適用於我的個人項目。 我仍然擁有所有豁免權,但很高興我快要放棄了!

    public partial class pUDP : Page
{
    public pUDP()
    {
        InitializeComponent();

        
    }

    private async void btnConnect_Click(object sender, RoutedEventArgs e)
    {

        var port = 11000;
        bool done = false;
        UdpClient listener = new UdpClient(port);

        IPEndPoint listenEndPoint = new IPEndPoint(IPAddress.Any, port);


        while (!done)
            {
             
                byte[] receivedData = await Task.Run(() => listener.Receive(ref listenEndPoint));
                tbRead.AppendText(Encoding.ASCII.GetString(receivedData));                  

            }

        listener.Close();


    }
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM