簡體   English   中英

后台工作者調用方法或其他方法

[英]Background Worker Call Method or something

我有一個效果很好的方法/程序,但是花很多時間才能完成它的工作,因此我想將其移交給后台工作人員,這樣人們仍然可以使用該應用程序。

這是代碼。 (我盡力減少了)

public partial class NetworkInformation : UserControl, INotifyPropertyChanged
    {
        public NetworkInformation()
        {
            InitializeComponent();
            Discovery();
        }
        public void Discovery()
        {
            GetIcon Icon = new GetIcon();
            BitmapImage IconOfComputer = null;
            List<DiscoveredComputer> NetworkedComputers = new List<DiscoveredComputer>();
            DirectoryEntry Discover = new DirectoryEntry("WinNT://Workgroup");
            BitmapImage On = Icon.LoadIcon(@"/Images/Icons/ComputerOn.ico");
            BitmapImage Off = Icon.LoadIcon(@"/Images/Icons/ComputerOff.ico");
            foreach (DirectoryEntry Node in Discover.Children)
            {
                try
                {
                    if (Node.Properties.Count > 0)
                    {
                        IconOfComputer = On;
                    }
                }
                catch
                {
                    IconOfComputer = Off;
                }
                if (Node.Name != "Schema") { NetworkedComputers.Add(new DiscoveredComputer { Image = IconOfComputer, ComputerName = Node.Name, MyToolTip = "Node Type = " + Node.SchemaEntry.Name }); }
            }
            ListView_LocalComputers.ItemsSource = NetworkedComputers;
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string PropertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }

    public class DiscoveredComputer : INotifyPropertyChanged
    {
        private string _ComputerName;
        public string ComputerName
        {
            get { return _ComputerName; }
            set
            {
                _ComputerName = value;
                this.NotifyPropertyChanged("ComputerName");
            }
        }
        private BitmapImage _Image;
        public BitmapImage Image { 
            get { return _Image; }
            set
            { 
                _Image = value;
                this.NotifyPropertyChanged("Image");
            }
        }
        private String _MyToolTip;
        public String MyToolTip
        {
            get { return _MyToolTip; }
            set
            {
                _MyToolTip = value;
                this.NotifyPropertyChanged("ToolTip");
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string PropertyName)
        {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }
    public class GetIcon
    {
        public BitmapImage IconStorage { get; set; }
        public BitmapImage LoadIcon(String IconPath)
        {
            BitmapImage GeneratedIcon = new BitmapImage();
            GeneratedIcon.BeginInit();
            GeneratedIcon.UriSource = new Uri("pack://application:,,," + IconPath, UriKind.RelativeOrAbsolute);
            GeneratedIcon.EndInit();
            IconStorage = GeneratedIcon;
            return GeneratedIcon;
        }
    }
}

這一切都很棒,無論如何...

這是我為背景工作者開發的代碼:

 public partial class MyBackgroundWorker : UserControl
    {
        WorkerData BGW;
        public MyBackgroundWorker()
        {
            InitializeComponent();

            BGW = new WorkerData();

            #region Workers Events
            BGW.ThisWorker.DoWork += new DoWorkEventHandler(Workers_DoWork);
            BGW.ThisWorker.ProgressChanged += new ProgressChangedEventHandler(Workers_Progress);
            BGW.ThisWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(Workers_Completed);
            BGW.ThisWorker.WorkerReportsProgress = true;
            BGW.ThisWorker.WorkerSupportsCancellation = true;
            #endregion


        }
        public void RibbonButton_EventClickStart(object sender, RoutedEventArgs e)
        {
            BGW.ThisWorker.RunWorkerAsync();
        }
        public void UserForm_Loaded(object sender, RoutedEventArgs e)
        {
        }
        public void RibbonButton_EventClick(object sender, RoutedEventArgs e)
        {
            BGW.ThisWorker.CancelAsync();
        }
        public void Workers_DoWork(object sender, DoWorkEventArgs e)
        {

        }
        public void Workers_Progress(object sender, ProgressChangedEventArgs e)
        {
            BGW.ThisWorkersProgress = e.ProgressPercentage;
        }

        public void Workers_Completed(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled) { BGW.ThisWorkersResult = "Cancelled By User"; }
            else if (e.Error != null) { BGW.ThisWorkersResult = "Error Encountered: " + e.Error.Message; }
            else
            {
                BGW.ThisWorkersResult = "Task Completed Successfully";
                BGW.WorkersReturnObject = e.Result;
            }
        }
    }
    public class WorkerData
    {
        public BackgroundWorker ThisWorker { get; set; }
        public int ThisWorkersProgress { get; set; }
        public string ThisWorkersResult { get; set; }
        public object WorkersReturnObject { get; set; }
        public object ThisWorkersJob { get; set; }

        public WorkerData()
        {
            ThisWorker = new BackgroundWorker();
        }
    }

那么,如何讓我的后台工作者運行我創建的發現方法?

您需要在DoWork事件處理程序中進行工作。

我不知道您是否需要整個單獨的課程。 我更喜歡根據需要隨時創建它們。 我認為您會Workers_Completed ,在多個地方使用您的課程,然后在某些情況下決定要在Workers_Completed中做其他事情, Workers_Completed在某些情況下發生錯誤時要做不同的事情,並且一個課程可能最終成為糾結的痛苦。 不過那只是我的意見。

此外,在觸摸BackgroundWorker中的UI線程時必須非常小心。 在下面的示例中,我將您的節點數傳遞給DoWork事件,而不是使其直接接觸UI組件。 我還將列表傳遞給RunWorkerCompleted事件,以便在嘗試將列表附加到ListView時回到主線程。

var bw = new BackgroundWorker();

bw.DoWork += (s, e) =>
  {
    var nodePropertiesCount = (int)e.Argument;

    // the guts of `Discovery` go in here

    e.Result = NetworkedComputers;
  };

bw.RunWorkerCompleted += (s, e) =>
  {
    if (e.Error != null)
    {
        // Task Completed Successfully
        ListView_LocalComputers = (List<DiscoveredComputer>)e.Result;
    }
    else
    {
        // Error Encountered
    }
  };

bw.RunWorkerAsync(Node.Properties.Count);

SLaks的答案是正確的,但是您顯然不明白這意味着什么。 我建議采取Discover()的膽量,然后將其放入Workers_DoWork()方法中,如下所示:

public void Workers_DoWork(object sender, DoWorkEventArgs e)
{
    var backgroundWorker = sender as BackgroundWorker;
    GetIcon Icon = new GetIcon();
    BitmapImage IconOfComputer = null;
    List<DiscoveredComputer> NetworkedComputers = new List<DiscoveredComputer>();
    DirectoryEntry Discover = new DirectoryEntry("WinNT://Workgroup");
    BitmapImage On = Icon.LoadIcon(@"/Images/Icons/ComputerOn.ico");
    BitmapImage Off = Icon.LoadIcon(@"/Images/Icons/ComputerOff.ico");

    while (!backgroundWorker.CancellationPending)
    {
        foreach (DirectoryEntry Node in Discover.Children)
        {
            try
            {
                if (Node.Properties.Count > 0)
                {
                    IconOfComputer = On;
                }
            }
            catch
            {
                IconOfComputer = Off;
            }
            if (Node.Name != "Schema") { NetworkedComputers.Add(new DiscoveredComputer { Image = IconOfComputer, ComputerName = Node.Name, MyToolTip = "Node Type = " + Node.SchemaEntry.Name }); }
        }
        break;
    }
    if(backgroundWorker.CancellationPending)
    {
        e.Cancel = true;
    }
    else
    {
        e.Result = NetworkedComputers;
    }
}

然后像這樣修改您的Workers_Completed()

public void Workers_Completed(object sender, RunWorkerCompletedEventArgs e)
{
  if (e.Cancelled) { BGW.ThisWorkersResult = "Cancelled By User"; }
  else if (e.Error != null) { BGW.ThisWorkersResult = "Error Encountered: " + e.Error.Message; }
  else
  {
      BGW.ThisWorkersResult = "Task Completed Successfully";
      //BGW.WorkersReturnObject = e.Result;
        //background worker can't touch UI components
        ListView_LocalComputers.ItemsSource = e.Result as List<DiscoveredComputer>;
  }
}

我建議進行這些更改或類似的更改,因為后台工作人員無法修改/訪問UI組件(如ListView),因此它必須傳遞回該值以用於ListView視圖的Result屬性。 我還提供了一種檢測取消的簡單方法; 我將進度報告留給您實施。

暫無
暫無

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

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