【问题标题】:C# Multiple Tasks and report progress [duplicate]C#多个任务和报告进度[重复]
【发布时间】:2021-05-20 15:03:16
【问题描述】:

我需要一些关于多项任务报告 C# 进度的帮助。我正在尝试在Xamarin 中使用,但为了简化,以下代码 sn-ps 是使用WindowsForm (WinForms) 制作的。

我需要运行一个执行任务的加载表单。此任务应向加载表单报告其进度,更改控制状态消息标签的属性。

到目前为止,我尝试的所有方法都不起作用。任务运行时,加载表单不会更新其状态消息。那么,我应该在哪里声明 Progress 变量,我应该如何将它传递给任务?这种沟通应该如何进行?

这是我的主要形式:

    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }


        private async void button1_Click(object sender, EventArgs e)
        {

            frmLoading loading = new frmLoading();

            // THIS BLOCK SHOUD BE HERE?
                Progress<string> progress = new Progress<string>(updateValue =>
                {
                    loading.ChangeMessage(updateValue);
                });
            //END


            loading.Start(() => Count(loading.progress)); //PROGRESS from LOADING or from this class?

            loading.ShowDialog();
        }


        private async Task<int> Count(IProgress<string> progress)
        {

            int returnValue = 0;

            for (int i = 0; i < 100; i++)
            {

                Thread.Sleep(100);

                if (progress != null)
                {

                    if (i <= 20)
                    {
                        progress.Report("Keep waiting...");
                    }
                    else if (i > 20 && i <= 40)
                    {
                        progress.Report("Hold on...");
                    }
                    else if (i > 40 && i <= 80)
                    {
                        progress.Report("So close!");
                    }
                    else
                    {
                        progress.Report("All right!");
                    }

                }

                returnValue = i;
            }

            await Task.Run(() => { MessageBox.Show("Completed!"); });

            return returnValue;

        }

    }

这是我的加载表单:

        public partial class frmLoading : Form, INotifyPropertyChanged
    {

        private Func<Task<int>> taskParam;

        public Progress<string> progress;

        public event PropertyChangedEventHandler PropertyChanged;

        public string currentMessage { get; set; }

        public frmLoading()
        {
            InitializeComponent();

            progress = new Progress<string>(updateMessage => {
                currentMessage = updateMessage;
            });

        }

        public async Task<int> StartTask()
        {

            return await taskParam();

        }

        private async void button1_Click(object sender, EventArgs e)
        {
            await StartTask();
        }

        public void Start(Func<Task<int>> taskParam)
        {
            this.taskParam = taskParam;
        }

        public void ChangeMessage(string newMessage)
        {
            currentMessage = newMessage;
        }


        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {

            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));

            if (propertyName.Equals(nameof(currentMessage)))
                lblProgress.Text = currentMessage;

        }

    }

【问题讨论】:

  • 您使用Thread.Sleep() 表示工作,但这只会阻塞线程。它没有为线程提供任何响应窗口消息的方式,而更新窗口需要这些消息。使用 Task.Delay() 代替,每个副本。

标签: c# multithreading winforms xamarin task


【解决方案1】:

到目前为止我尝试的所有方法都不起作用。

这是因为Count 几乎是完全同步的。如果你去掉了await Task.Run,那么编译器会警告你它将同步运行。

如果您有异步工作要做,请将Thread.Sleep 替换为await Task.Delay。如果您有同步的工作要做,那么在Task.Run 内完成这项工作,如下所示:

loading.Start(() => Task.Run(() => Count(loading.progress)));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-28
    • 1970-01-01
    • 2022-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多