繁体   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