簡體   English   中英

在對象中使用BackgroundWorker並更新UI

[英]Using BackgroundWorker in an object and updating UI

編輯:我希望能到達某個地方

這是我所擁有的,但我不太確定如何將我的bcLoad.ReportProgress(i)委托給創建的對象(即如何使委托以便可以傳遞)。 我已經創建了有效的對象事件(我可以調用我的對象方法,我可以看到在讀取行時觸發的更改)。 我知道objectChanged何時工作(寫入控制台)。 但是,bcLoad_RunWorkerCompleted似乎不起作用,if語句中的代碼永遠不會執行,所以我在某處出錯了。 但是文件加載了。

有人可以請說明如何創建委托,然后使用傳遞委托的哪個部分(我假設在對象中)以及為什么bcLoad_RunWorkerComplete為null。 這是我第一次在c#中使用事件,代表和后台工作者

/*
The object which does file operations
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using System.Windows.Forms;
using System.ComponentModel;
using System.Data;

namespace aodProductionViewer
{
    public class fileOperationsSpecial
    {
        public event EventHandler Changed;

        protected virtual void OnChanged(EventArgs e)
        {
            if (Changed != null)
            {
                Changed(this, e);
            }
        }

        public fileOperationsSpecial() 
        {        }

        /// <summary>
        /// Count the number of lines in the file specified.
        /// </summary>
        /// <param name="f">The filename to count lines in.</param>
        /// <returns>The number of lines in the file.</returns>
        static long CountLinesInFile(string f)
        {
            long count = 0;
            try
            {
                using (StreamReader r = new StreamReader(f))
                {
                    string line;
                    while ((line = r.ReadLine()) != null)
                    {
                        count++;
                    }
                }
            }
            catch (Exception err)
            {
                string strTemp = "Error get number of lines for save game file. \n" +
                                err.ToString();
                errorDialog errDiag = new errorDialog("save game line count",
                                        strTemp, true);
            }
            return count;
        }

        /// <summary>
        /// Use this to readin in a file
        /// </summary>
        /// <param name="strPath">Path of file to read in</param>
        /// <returns>a string array of the file</returns>
        public string[] readFile(string strPath)
        {
            long lng_LineCount = CountLinesInFile(strPath);
            string[] strReadIn = new string[lng_LineCount];
            try
            {
                long lngCount = 0;
                using (StreamReader reader = new StreamReader(strPath))
                {
                    String line;
                    while ((line = reader.ReadLine()) != null)
                    {
                        strReadIn[lngCount] = line;
                        lngCount++;
                        OnChanged(EventArgs.Empty);
                    }
                }

            }
            catch (Exception err)
            { //            
            }

            return strReadIn;
        }
   }
}

/*
Event Listner
*/
using System;
using System.Collections.Generic;
using System.Text;

namespace aodProductionViewer
{
    class EventListener
    {
        private fileOperationsSpecial FPS;

        public EventListener(fileOperationsSpecial _fps)
        {
            FPS = _fps;
            FPS.Changed += new EventHandler(objectChanged);
        }

        private void objectChanged(object sender, EventArgs e)
        {            //changed has occured
        }

        public void Detach()
        {
            FPS.Changed -= new EventHandler(objectChanged);
            FPS = null;
        }
    }
}

/*
The backgroundWorker code (Part of)
*/

    BackgroundWorker bcLoad = new BackgroundWorker();

    private void btt_load_save_game_Click(object sender, EventArgs e)
    {
        //Do some file dialog stuff
        string strPath = null;
        bcLoad.RunWorkerAsync(strPath);
    }

    void bcLoad_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        tb_ProgressBar.Value = e.ProgressPercentage;
    }

    void bcLoad_DoWork(object sender, DoWorkEventArgs e)
    {
        string strPath = e.Argument as string;
        fileOperationsSpecial FPS = new fileOperationsSpecial();
        EventListener listener = new EventListener(FPS);
        string strArray = FPS.readFile(strPath);
        listener.Detach();
    }

    void bcLoad_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Result != null)
        {
            //Everything done
            tb_ProgressBar.Visible = false;
        }
    }

我有使用BackgroundWorker做一些工作並更新UI進度和完成的要點,我現在有一些簡單的東西你可以看到,我傳遞一個字符串(這是一條路徑)然后我會讀取文件並更新進度,目前我只是在休眠線程並為演示設置進度。 我還打算返回一個對象(字符串數組),但我還沒有解決這個問題。

現在我的問題是,如何在我的表單創建的對象中完成所有這些操作並仍然更新我的UI? 我有一個目前對文件進行操作的對象(即讀取文件,寫入,獲取信息)。

目前,根據我的理解,下面的演示為Form> BackgroundWorker> Update表單以獲取進度。

我想要它去

表單>創建對象> BackgroundWorker>進度更新表單>返回字符串數組

我看過並且沒有做過任何一個例子的正面或反面,所以我想我會問那些會知道的人。 這甚至可能嗎? 我想要的目標是從我的表單中刪除任何文件處理,以便更容易管理和維護。

關於如何做到這一點的完整代碼示例將是太棒了!

這是我到目前為止所理解的(記住只是為了一個例子,這不會編譯)

BackgroundWorker bcLoad = new BackgroundWorker();

    public frm_ProductionViewer()
    {
        InitializeComponent();
        load_settings();
        bcLoad.DoWork += new DoWorkEventHandler(bcLoad_DoWork);
        bcLoad.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bcLoad_RunWorkerCompleted);

        bcLoad.WorkerReportsProgress = true;
        bcLoad.ProgressChanged += new ProgressChangedEventHandler(bcLoad_ProgressChanged);

        bcLoad.WorkerSupportsCancellation = true;
    }

private void btt_load_save_game_Click(object sender, EventArgs e)
    {

        ts_label_GameLoaded.Text = "Loading";
        bcLoad.RunWorkerAsync(strPath);
    }

void bcLoad_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        tb_ProgressBar.Value = e.ProgressPercentage;
    }

    void bcLoad_DoWork(object sender, DoWorkEventArgs e)
    {
            string strPath = e.Argument as string;
            //load file
            //Update progress
            bcLoad.ReportProgress(80);
            Thread.Sleep(300 * 5);
            bcLoad.ReportProgress(100);
    }

    void bcLoad_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Result != null)
        {
            textBox1.Text = "done";
        }
        tb_ProgressBar.Visible = false; ;
        ts_label_GameLoaded.Text = "Loaded";
    }

您的對象(使用文件)最好不要依賴於GUI或Bgw。

因此,請將您的Bgw與您的表格保持在一起,並調用DoWork的對象形式。

要報告反饋,您的對象需要一個事件(或者采用委托參數的主要方法)。

在該事件的處理程序中(在工作線程上調用),調用bcLoad.ReportProgress(百分比)。


對編輯的反應:

  • 你需要一個具有Percentage空間的EventArgs類型,比如EventHandler<ProgressEventArgs> ,你可能需要編寫ProgressEventArgs。

  • 我不認為你想要一個單獨的EventListener類。 這是Forms工作。 這會讓你:

class Form ...
{
    private void objectChanged(object sender, ProgressEventArgs e)
    {   //changed has occured
        // trigger the Bgw event
        // or use Form.Invoke here to set the progress directly
        bcLoad.ReportProgress(e.Percentage);          
    }

}

因此,“更改”現在可以過濾2個事件處理程序。 1打破FPS的依賴,1同步到Form。

如果您希望類(表單除外)封裝后台工作程序,則一種方法是向此類添加事件並在表單中訂閱此事件:

  • X類封裝后台工作程序並發布“完成”事件
  • 表單創建類X的實例,以及“完成”事件的事件處理程序
  • 表單調用Class X的實例“Do async work”方法並繼續
  • 當異步工作通過Done事件完成,傳遞字符串或表單所需的任何狀態時,類X的實例通知表單

暫無
暫無

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

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