C# 背景工作者。如何通过树视图导航显示当前流程?

C# 背景工作者。如何通过树视图导航显示当前流程?,c#,winforms,C#,Winforms,情景1. 1.用户。按下“开始”按钮 2.节目。在“flowLayoutPanel1”中创建用户元素“ucBackgroundWorker”的实例 3.节目。在“treeView1”中创建一个节点 “场景1”可以无限次重复 情景2. 有: -在“flowLayoutPanel1”中启动了几个进程 -在“treeView1”中有一个进程树 场景: 1.用户。将光标移动到“树视图1” 2.节目。在“flowLayoutPanel2”中显示流程(实例 光标所在节点的“ucBackgroundWorke

情景1.
1.用户。按下“开始”按钮
2.节目。在“flowLayoutPanel1”中创建用户元素“ucBackgroundWorker”的实例
3.节目。在“treeView1”中创建一个节点

“场景1”可以无限次重复

情景2.
有: -在“flowLayoutPanel1”中启动了几个进程
-在“treeView1”中有一个进程树

场景:
1.用户。将光标移动到“树视图1”
2.节目。在“flowLayoutPanel2”中显示流程(实例
光标所在节点的“ucBackgroundWorker”“)

据我所知,我试图实现这个场景(场景1+场景2)。 我认为用户元素实例可以被分配索引, 然后,根据索引,显示在“flowLayoutPanel2”中。
对于测试,此脚本的按钮制作了一个按钮“btShowTheProces”
但该项目不起作用。
调试时,我收到一个错误。
表格3.cs

flowLayoutPanel1.Controls.Add (ucBgWorker [i_ucBWrk]);
错误“对象引用未指向对象的实例。”
ucBgWorker=null

您的问题
1.如何修复错误?
2.我是否正确地解决了问题?
3.实现此场景的其他方法是什么?
例如,进程未绑定到索引,而是绑定到“字符串”?
比如像这样的

string i_ucBWrk;
i_ucBWrk = "process_1";
flowLayoutPanel1.Controls.Add (ucBgWorker [i_ucBWrk]);
Form3.cs

namespace rsh
{
    public partial class ucBackgroundWorker : UserControl
    {
        BackgroundWorker bgWorker = null;
        public event Action<string, EventArgs> Done;
        public event Action<string, EventArgs> Cancel;

        private static bool m_continue = true;

        // Уведомляет один или более ожидающих потоков о том, что произошло событие. Этот класс не наследуется.
        // https://msdn.microsoft.com/ru-ru/library/system.threading.manualresetevent(v=vs.110).aspx
        private ManualResetEvent _resetEvent = new ManualResetEvent(false);
        //Semaphore sWaiter = new Semaphore(0, 1);


        public ucBackgroundWorker()
        {
            InitializeComponent();

            bgWorker = new BackgroundWorker();

            bgWorker.WorkerSupportsCancellation = true;
            bgWorker.WorkerReportsProgress = true;

            bgWorker.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            bgWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
        }

        public void Run(int counter)
        {
            if (!bgWorker.IsBusy)
            {
                bgWorker.RunWorkerAsync(counter);
            }
            _resetEvent.Set();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int input = int.Parse(e.Argument.ToString());

            this.BeginInvoke((MethodInvoker)delegate
            {
                lblStatus.Text = "Running";
            });

            for (int i = 1; i <= input; i++)
            {
                _resetEvent.WaitOne();
                Thread.Sleep(1000);
                (sender as BackgroundWorker).ReportProgress(i*1); // шаг
                // (sender as BackgroundWorker).ReportProgress(i * 10);
                if ((sender as BackgroundWorker).CancellationPending)
                {
                    this.BeginInvoke((MethodInvoker)delegate
                    {
                        lblStatus.Text = "Cancel";
                    });

                    e.Cancel = true;
                    return;
                }
            }
            Thread.Sleep(1000);
        }


        // This event handler deals with the results of the 
        // background operation.
        // Этот обработчик событий имеет дело с результатами
        // фоновая операция.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown. 
            // Сначала обрабатываем случай, когда было создано исключение.
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                if (Cancel != null)
                    Cancel(this.Name, EventArgs.Empty);
            }
            else
            {
                this.BeginInvoke((MethodInvoker)delegate
                {
                    lblStatus.Text = "Done";
                });

                if (Done != null)
                    Done(this.Name, EventArgs.Empty);
            }
            _resetEvent.Reset();
        }

        // This event handler updates the progress bar. 
        // Этот обработчик событий обновляет индикатор выполнения.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pBar.Refresh();
            pBar.Value = e.ProgressPercentage;
        }



        // *** *** *** ***
        // *** КНОПКИ  ***
        // *** *** *** ***

        // Cancel
        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (bgWorker.IsBusy)
            {
                bgWorker.CancelAsync();
            }
        }

        // Pause
        private void btnPause_Click(object sender, EventArgs e)
        {
            if (bgWorker.IsBusy)
            {
                if (btnPause.Text.ToUpper() == "PAUSE")
                {
                    btnPause.Text = "Resume";
                    m_continue = false;
                    _resetEvent.Reset();
                }
                else 
                if (btnPause.Text.ToUpper() == "RESUME")
                {

                    btnPause.Text = "Pause";
                    m_continue = true;
                    _resetEvent.Set();

                }
            }
        }


    }
}
名称空间rsh { 公共部分类表单3:表单 { //ucBackgroundWorker[]ucBgWorker=null

    int i_ucBWrk=0;
    private ucBackgroundWorker[] ucBgWorker;

    int procNumb;

    public Form3()
    {
        InitializeComponent();
    }

    // после выбора узла дерева
    void treeView1_AfterSelect(object sender, TreeViewCancelEventArgs e)
    {

    }

    private void btnStart_Click(object sender, EventArgs e)
    {
        i_ucBWrk++;

        ucBgWorker[i_ucBWrk] = new ucBackgroundWorker();

        // ucBgWorker[i_ucBWrk].Done += new Action<string, EventArgs>(Worker_Done);
        // ucBgWorker[i_ucBWrk].Cancel += new Action<string, EventArgs>(Worker_Cancel);

        flowLayoutPanel1.Controls.Add(ucBgWorker[i_ucBWrk]);

        ucBgWorker[i_ucBWrk].Run(1);            
        // ucBgWorker.Run(Convert.ToInt32(textBox1.Text));
    }

    void Worker_Done(string arg, EventArgs evtarg)
    {
        label1.Text = arg + " Done One";
        //System.Threading.Thread.Sleep(1000);
    }

    void Worker_Cancel(string arg, EventArgs evtarg)
    {
        label1.Text = arg + " Cancel Click";
        //System.Threading.Thread.Sleep(1000);
    }


    //  show the process
    private void btShowTheProces_Click(object sender, EventArgs e)
    {
        procNumb = Convert.ToInt32(numericUpDown1.Value);

        flowLayoutPanel2.Controls.Clear();
        flowLayoutPanel2.Controls.Add(ucBgWorker[procNumb]);
    }
}
int i_ucBWrk=0;
私人ucBackgroundWorker[]ucBgWorker;
int-procnum;
公共表格3()
{
初始化组件();
}
// после выбора узла дерева
void treeView1_AfterSelect(对象发送方,treeviewcanceleventergs e)
{
}
私有void btnStart_单击(对象发送方,事件参数e)
{
i_ucBWrk++;
ucBgWorker[i_ucBWrk]=新的ucBackgroundWorker();
//ucBgWorker[i_ucBWrk].Done+=新操作(Worker_Done);
//ucBgWorker[i\u ucBWrk]。取消+=新操作(Worker\u Cancel);
flowLayoutPanel1.Controls.Add(ucBgWorker[i_ucBWrk]);
ucBgWorker[i_ucBWrk]。运行(1);
//运行(Convert.ToInt32(textBox1.Text));
}
无效工作线程完成(字符串参数、事件参数evtarg)
{
label1.Text=arg+“完成一项”;
//系统线程线程睡眠(1000);
}
无效工作程序\u取消(字符串参数、事件参数evtarg)
{
label1.Text=arg+“取消单击”;
//系统线程线程睡眠(1000);
}
//展示过程
private void btshow theproces\u Click(对象发送者,事件参数e)
{
procnum=Convert.ToInt32(numericUpDown1.Value);
flowLayoutPanel2.Controls.Clear();
flowLayoutPanel2.Controls.Add(ucBgWorker[procNumb]);
}
}
}

ucBackgroundWorker.cs

namespace rsh
{
    public partial class ucBackgroundWorker : UserControl
    {
        BackgroundWorker bgWorker = null;
        public event Action<string, EventArgs> Done;
        public event Action<string, EventArgs> Cancel;

        private static bool m_continue = true;

        // Уведомляет один или более ожидающих потоков о том, что произошло событие. Этот класс не наследуется.
        // https://msdn.microsoft.com/ru-ru/library/system.threading.manualresetevent(v=vs.110).aspx
        private ManualResetEvent _resetEvent = new ManualResetEvent(false);
        //Semaphore sWaiter = new Semaphore(0, 1);


        public ucBackgroundWorker()
        {
            InitializeComponent();

            bgWorker = new BackgroundWorker();

            bgWorker.WorkerSupportsCancellation = true;
            bgWorker.WorkerReportsProgress = true;

            bgWorker.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
            bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
            bgWorker.ProgressChanged += new ProgressChangedEventHandler(backgroundWorker1_ProgressChanged);
        }

        public void Run(int counter)
        {
            if (!bgWorker.IsBusy)
            {
                bgWorker.RunWorkerAsync(counter);
            }
            _resetEvent.Set();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            int input = int.Parse(e.Argument.ToString());

            this.BeginInvoke((MethodInvoker)delegate
            {
                lblStatus.Text = "Running";
            });

            for (int i = 1; i <= input; i++)
            {
                _resetEvent.WaitOne();
                Thread.Sleep(1000);
                (sender as BackgroundWorker).ReportProgress(i*1); // шаг
                // (sender as BackgroundWorker).ReportProgress(i * 10);
                if ((sender as BackgroundWorker).CancellationPending)
                {
                    this.BeginInvoke((MethodInvoker)delegate
                    {
                        lblStatus.Text = "Cancel";
                    });

                    e.Cancel = true;
                    return;
                }
            }
            Thread.Sleep(1000);
        }


        // This event handler deals with the results of the 
        // background operation.
        // Этот обработчик событий имеет дело с результатами
        // фоновая операция.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            // First, handle the case where an exception was thrown. 
            // Сначала обрабатываем случай, когда было создано исключение.
            if (e.Error != null)
            {
                MessageBox.Show(e.Error.Message);
            }
            else if (e.Cancelled)
            {
                if (Cancel != null)
                    Cancel(this.Name, EventArgs.Empty);
            }
            else
            {
                this.BeginInvoke((MethodInvoker)delegate
                {
                    lblStatus.Text = "Done";
                });

                if (Done != null)
                    Done(this.Name, EventArgs.Empty);
            }
            _resetEvent.Reset();
        }

        // This event handler updates the progress bar. 
        // Этот обработчик событий обновляет индикатор выполнения.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pBar.Refresh();
            pBar.Value = e.ProgressPercentage;
        }



        // *** *** *** ***
        // *** КНОПКИ  ***
        // *** *** *** ***

        // Cancel
        private void btnCancel_Click(object sender, EventArgs e)
        {
            if (bgWorker.IsBusy)
            {
                bgWorker.CancelAsync();
            }
        }

        // Pause
        private void btnPause_Click(object sender, EventArgs e)
        {
            if (bgWorker.IsBusy)
            {
                if (btnPause.Text.ToUpper() == "PAUSE")
                {
                    btnPause.Text = "Resume";
                    m_continue = false;
                    _resetEvent.Reset();
                }
                else 
                if (btnPause.Text.ToUpper() == "RESUME")
                {

                    btnPause.Text = "Pause";
                    m_continue = true;
                    _resetEvent.Set();

                }
            }
        }


    }
}
名称空间rsh
{
公共部分类ucBackgroundWorker:UserControl
{
BackgroundWorker bgWorker=null;
已采取的公共活动行动;
公众活动取消;
私有静态bool m_continue=true;
// Уведомляет один или более ожидающих потоков о том, что произошло событие. Этот класс не наследуется.
// https://msdn.microsoft.com/ru-ru/library/system.threading.manualresetevent(v=vs.110).aspx
private ManualResetEvent _resetEvent=新的ManualResetEvent(错误);
//信号量交换器=新信号量(0,1);
公共ucBackgroundWorker()
{
初始化组件();
bgWorker=新的BackgroundWorker();
bgWorker.WorkerSupportsScanCellation=true;
bgWorker.WorkerReportsProgress=true;
bgWorker.DoWork+=新的doworkenventhandler(后台工作1_DoWork);
bgWorker.RunWorkerCompleted+=新的RunWorkerCompletedEventHandler(backgroundWorker1\u RunWorkerCompleted);
bgWorker.ProgressChanged+=新的ProgressChangedEventHandler(backgroundWorker1\u ProgressChanged);
}
公共无效运行(整数计数器)
{
如果(!bgWorker.IsBusy)
{
bgWorker.RunWorkerAsync(计数器);
}
_resetEvent.Set();
}
私有void backgroundWorker1\u DoWork(对象发送方,DoWorkEventArgs e)
{
int input=int.Parse(如Argument.ToString());
此.BeginInvoke((MethodInvoker)委托
{
lblStatus.Text=“正在运行”;
});

对于(int i=1;i您从不初始化ucBgWorker数组

将您的代码更改为此

private ucBackgroundWorker[] ucBgWorker = new ucBackgroundWorker[10];
这样做的问题是,数组的最大值设置为10

您最好使用以下列表:

private List<ucBackgroundWorker> ucBgWorker = new List<ucBackgroundWorker>();
您仍然可以按索引访问项目:

ucBackgroundWorker item = ucBgWorker[0];

只要列表中有项目。

错误“对象引用不指向对象的实例”“总是有相同的原因:您试图取消引用不包含任何对象的对象变量。若要更正此问题,请找出
ucBgWorker
为空的原因。@RobertHarvey我尝试过这样做,但我可以理解为什么会发生这种情况。您需要提供数组的大小:
private ucBackgroundWorker[]ucBgWorker;
私有ucBackgroundWorker[]ucBgWorker=new ucBackgroundWorker[somevalue];
如果使用列表,我如何执行“场景1”的步骤3?如何将树节点与流程关联?因此树的构建方式如下:-流程1--流程2--流程3请参见问题图。元素“treeView1”@koverflow,当您将项目添加到树状视图时,您将项目的标记设置为您创建的ucBackgroundWorker实例,然后当您选择您投射项目的树状视图项目时。Tag int