执行可以使用Windows窗体按钮取消的后台进程

我需要启动一个后台进程(Solver),该进程从我的主窗体(Form1)接收数据并在ProgressBar中以新窗体(FormStatus)指示其进度。我决定从Form1启动FormStatus,然后从FormStatus的OnLoad启动,以在单独的线程中执行规划求解过程。在求解器执行的任何时候,我都可以使用FormStatus中的ButtonStop中止它。如果直接启动,该过程将阻止该表单。

如果进程被按钮终止,则抛出异常,否则(如果计算完成),求解器返回空字符串并关闭FormStatus。

主要Form1的代码:

using System;
using System.Windows.Forms;

namespace CS_Threads
{
    public partial class Form1 : Form
    {
        // Contains some data
        public class CData
        { public int Int { set; get; } }

        private CData data;

        public Form1()
        {
            InitializeComponent();

            data = new CData() { Int = 100 };
        }

        // On ButtonGO press open FormStatus to start the solver
        private void ButtonGO_Click(object sender,EventArgs e)
        {
            int result;

            using (FormStatus f = new FormStatus(data))
            {
                f.ShowDialog();
                result = f.Result;
            }

            // Fill the RTBox according to calculation results
            if (result < 0) RTBox.Text = "Failed";
            else RTBox.Text = "Success";
        }
    }
}

FormStatus的代码:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CS_Threads
{
    public partial class FormStatus : Form
    {
        private Form1.CData data;
        private CancellationTokenSource source;

        public int Result { private set; get; }

        public FormStatus(Form1.CData d)
        {
            InitializeComponent();

            data = d; // Didn't find a better way to pass the class reference. Maybe make this member public in Form1?
            Result = -1; // Default value of Result if form was closed or process terminated
            source = new CancellationTokenSource();
        }

        // On ButtonStop press stop the Solver and close form
        private void ButtonStop_Click(object sender,EventArgs e)
        {
            source.Cancel();
            Close();
        }

        // On form load launch Solver: Warning CS1998 This async method lacks 'await' operators and will run synchronously.Consider using the 'await' operator...
        private async void FormStatus_Load(object sender,EventArgs e)
        {
            Task<string> t = Task.Run(() => Solver(data,this,source.Token));
            string res = t.Result;
        }

        // Solver: Same warning CS1998
        private static async Task<string> Solver(Form1.CData data,FormStatus f,CancellationToken ct)
        {
            try
            {
                // Do some calculations
                long max = 1000;
                for (long i = 0; i < max && !ct.IsCancellationRequested; i++)
                    for (long j = 0; j < max && !ct.IsCancellationRequested; j++)
                    {
                        data.Int = 10;
                        f.ProgressBar.Value = (int)(((double)i / (double)max) * ((double)j / (double)max) * 100.0);
                    }

                if (!ct.IsCancellationRequested)
                {
                    f.Result = 0;
                    f.Close();
                }
                else throw new Exception("Task has been cancelled");
            }
            catch (Exception ex)
            { return ex.ToString(); }

            return null;
        }
    }
}

目前,我在FormStatus中有两个警告,并且该过程在Solver的第一次迭代中终止,并在'string res'中引发异常:System.InvalidOperationException:跨线程操作无效:从其他线程访问的控件'ProgressBar'比创建它的线程要多。

我刚刚开始使用线程,所以可能会有一些非常愚蠢的东西...

pcccainao 回答:执行可以使用Windows窗体按钮取消的后台进程

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3144954.html

大家都在问