簡體   English   中英

在C#Form應用程序中使用BackGroundWorker更新UI線程

[英]updating UI thread using BackGroundWorker in C# Form application

我有一個耗時的任務,需要測試幾個網絡連接。 在下面的示例中,我將其限制為一個連接。 通常,連接會快速返回,但是可能會發生無法建立連接從而導致套接字超時的情況。 在此期間,我想在表單中顯示一個“ idler” gif,當連接成功時,應用程序應將“表單”中的“圖像”更改為一些綠色復選圖標,或者在連接失敗的情況下,將紅色圖標“ stopper”更改為顯示。

不知何故,我無法使惰輪gif變得可見並具有動畫效果。 要模擬失敗的連接,可以輸入無效的端口號或不存在的地址。

有什么線索我想念或做錯了什么嗎?

    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        ///         
     #region BackgroundWorker

        private System.ComponentModel.BackgroundWorker backgroundWorker = new System.ComponentModel.BackgroundWorker();
        private delegate void SomeLongRunningMethodHandler(object sender, EventArgs e);

     #endregion
        private System.ComponentModel.IContainer components = null;

        Button button,button2;
        static Socket socket;
        static bool success;
        private static bool done;
        private Label lbl1;
        private Label lbl2;
        private TextBox address;
        private TextBox port;
        private PictureBox p;
        private static String port_number,host;


        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        private void RunTest(object o,EventArgs e)
        {
            p.Visible = true;
            SomeLongRunningMethodHandler synchronousFunctionHandler =
                default(SomeLongRunningMethodHandler);
            synchronousFunctionHandler = 
                TestConnection;
            synchronousFunctionHandler.Invoke(o, e);
        }

        private void TestConnection(object o, EventArgs e)
        {
            host = address.Text;
            port_number = port.Text;
           if (null != socket)
            {
                socket.Close();
            }

             Thread.Sleep(1000);
             IPEndPoint myEndpoint = new IPEndPoint(0, 0);


            IPHostEntry remoteMachineInfo = Dns.GetHostEntry(host);
            IPEndPoint serverEndpoint = new IPEndPoint(remoteMachineInfo.AddressList[0],
                int.Parse(port_number));



            socket = new Socket(myEndpoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                socket.Connect(serverEndpoint);
                success = true;
                p.Image = global::BlockingUI.Properties.Resources.accept;
            }
            catch
            {
                success = false;
                p.Image = global::BlockingUI.Properties.Resources.stopper;
            }
            done = true;
        }  


        private void ExitApp(object o, EventArgs e)
        {
            Application.Exit();
        }

    }

如果您確實想使用BackgroundWorker ,那么它(或接近它的東西)應該為您指明正確的方向。 您正在創建BackgroundWorker對象,但是對此不執行任何操作。 不允許BackgroundWorker對象訪問UI元素,因為它們是UI線程所擁有的,但是您可以傳遞UI值,就像我在此處使用Tuple (如果需要,您也可以創建自己的類來保存這些值),並且然后在工作程序完成后從UI線程修改UI。

private struct ConnectionProperties
{
    public string Address;
    public string Port;
}

private void RunTest(object o, EventArgs e)
{
    BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();

    worker.RunWorkerCompleted += TestComplete;
    worker.DoWork += TestConnection;

    p.Visible = true;

    //worker.RunWorkerAsync(new Tuple<string, string>(address.Text, port.Text));
    worker.RunWorkerAsync(new ConnectionProperties{ Address = address.Text, Port = port.Text });
}

private void TestConnection(object sender, DoWorkEventArgs e)
{
    bool success = false;
    //var connection = e.Argument as Tuple<string, string>;
    var connection = (ConnectionProperties)e.Argument;

    if (null != socket)
    {
        socket.Close();
    }

    Thread.Sleep(1000);

    IPEndPoint myEndpoint = new IPEndPoint(0, 0);
    IPHostEntry remoteMachineInfo = Dns.GetHostEntry(connection.Address);
    IPEndPoint serverEndpoint = new IPEndPoint(remoteMachineInfo.AddressList[0],
      int.Parse(connection.Port));

    socket = new Socket(myEndpoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

    try
    {
        socket.Connect(serverEndpoint);
        success = true;
    }
    catch
    {
        success = false;
    }

    e.Result = success;
}

// Define other methods and classes here
private void TestComplete(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error == null)
    {
        var success = (bool)e.Result;
        if (success)
        {
            p.Image = global::BlockingUI.Properties.Resources.accept;
        }
        else
        {
            p.Image = global::BlockingUI.Properties.Resources.stopper;
        }
    }
    else
    {
        //unexpected error, show message or whatever
    }
}

好吧,我是用自己的線程完成的。 通常,您使用長時間運行的任務運行線程,並在需要時調用Control.Invoke()並使用一個指向將在UI上運行的函數的委托。 看來您正在使用后台工作線程更改UI,這是不允許的。

此外,在Winforms中,必須調用Control.Invalidate()來強制重新繪制UI並顯示新圖標。

暫無
暫無

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

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