Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 并行循环调用中的进度条_C#_.net_Multithreading_Task Parallel Library_Async Await - Fatal编程技术网

C# 并行循环调用中的进度条

C# 并行循环调用中的进度条,c#,.net,multithreading,task-parallel-library,async-await,C#,.net,Multithreading,Task Parallel Library,Async Await,我正在尝试在多线程环境中更新progressbar。我知道很多问题已经解决了这个问题,但是没有一个解决方案对我有效。 以下是我的代码的主干: public static void DO_Computation(//parameters) { //Intialisation of parameters Parallel.For(struct initialisation with local data) { //business logic //Call to updat

我正在尝试在多线程环境中更新progressbar。我知道很多问题已经解决了这个问题,但是没有一个解决方案对我有效。 以下是我的代码的主干:

public static void DO_Computation(//parameters) {
  //Intialisation of parameters

  Parallel.For(struct initialisation with local data) {
    //business logic
    //Call to update_progressbar (located in an another class, as the DO_Computation function is in Computation.cs class (not deriving from Form). 
    WinForm.Invoke((Action)delegate {Update_Progress_Bar(i);}); //WinForm is a class that exposes the  progressbar.
  }
}
这不起作用(progressbar在达到100%时处于冻结状态,这是正常的(我们可以在这件事中参考(实际上,这不是一种线程安全的操作方法))。 Microsoft site stiplates可将
并行。For
循环打包为
任务
例程,如下所示:

public static void DO_Computation(//parameters) {
  //Intialisation of parameters
  Task.Factory.StartNew(() =>
  {
    Parallel.For(struct initialosation with local data) {
      //business logic
      //Call to update_progressbar (ocated in an another class, as the DO_Computation function is in Computation.cs class (not deriving from Form). 
      WinForm.Invoke((Action)delegate {Update_Progress_Bar(i);}); //WinForm is a class that exposes the  progressbar.
      ..
    }
  });
});
但是,当调试线程直接脱离任务范围时,这也不起作用

编辑2:

基本上,我的问题分为三个部分:
Computation.cs
(其中
DO\u Computation
是公开的),
WinForm
是包含进度条的表单,
main window
是包含按钮的表单,单击该按钮可打开带有进度条的表单

我不清楚“任务”在这种情况下有什么用。 因为它不执行任何
并行操作就超出了任务范围

有什么想法吗

非常感谢,

编辑3:

我在Noseratio的帮助下升级了代码(对他来说太多了)。但是我也有同样的问题,任务中的代码从未执行过。我的代码现在看起来像:

DoComputation method
   //Some Initilasations here 
    Action enableUI = () =>
    {
    frmWinProg.SetProgressText("Grading Transaction...");
    frmWinProg.ChangeVisibleIteration(true);
    };
    Action<Exception> handleError = (ex) =>
    {
    // error reporting
    MessageBox.Show(ex.Message);
    };
    var cts = new CancellationTokenSource();
    var token = cts.Token;
    Action cancel_work = () =>
    {
    frmWinProg.CancelTransaction();
    cts.Cancel();
    };
    var syncConext = SynchronizationContext.Current;
    Action<int> progressReport = (i) =>
    syncConext.Post(_ => frmWinProg.SetIteration(i,GrpModel2F.NumOfSim, true), null);
    var task = Task.Factory.StartNew(() =>
    {
    ParallelLoopResult res = Parallel.For<LocalDataStruct>(1,NbSim, options,
    () => new DataStruct(//Hold LocalData for each thread),
    (iSim, loopState, DataStruct) => 
    //Business Logic 
    if (token.IsCancellationRequested)
    {
    loopState.Stop();
    }
    progressReport(iSim);
    //Business Logic
    return DataStruct;
    },
    (DataStruct) => 
    //Assiginig Results;
    });//Parallel.For end
    }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
    task.ContinueWith(_ =>
    {
    try
    {
    task.Wait();
    }
    catch (Exception ex)
    {
    while (ex is AggregateException && ex.InnerException != null)
    ex = ex.InnerException;
    handleError(ex);
    }
    enableUI();
    }, TaskScheduler.FromCurrentSynchronizationContext

docompution方法
//这里有一些初始条件
操作启用ui=()=>
{
frmWinProg.SetProgressText(“分级事务…”);
frmWinProg.ChangeVisibleIteration(真);
};
操作句柄错误=(ex)=>
{
//错误报告
MessageBox.Show(例如Message);
};
var cts=新的CancellationTokenSource();
var-token=cts.token;
操作取消工作=()=>
{
frmWinProg.CancelTransaction();
cts.Cancel();
};
var syncConext=SynchronizationContext.Current;
行动进度报告=(i)=>
synconext.Post(=>frmWinProg.SetIteration(i,GrpModel2F.numosim,true),null);
var task=task.Factory.StartNew(()=>
{
ParallelLoopResult res=并行。对于(1,NbSim,选项,
()=>新的数据结构(//为每个线程保存本地数据),
(iSim、loopState、数据结构)=>
//业务逻辑
if(令牌.IsCancellationRequested)
{
loopState.Stop();
}
进展报告(iSim);
//业务逻辑
返回数据结构;
},
(数据结构)=>
//辅助结果;
})//Parallel.For end
},标记,TaskCreationOptions.LongRunning,TaskScheduler.Default);
task.ContinueWith(=>
{
尝试
{
task.Wait();
}
捕获(例外情况除外)
{
while(ex是aggregateeexception&&ex.InnerException!=null)
ex=ex.InnerException;
handleError(ex);
}
enableUI();
},TaskScheduler.FromCurrentSynchronizationContext
())

请注意,Do_计算函数本身是从在其上运行BackGroundWorker的窗体调用的。

使用,并观察取消

一本好书,相关:

如果您需要以.NET 4.0为目标,但使用VS2012+开发,您仍然可以使用
async/await
,Microsoft为此提供了库

我已经组合了一个WinForms示例来说明上述所有内容。它还展示了如何观察
Parallel的取消。对于
循环,使用
ParallelLoopState.Stop()


非常感谢,NoStratio。不幸的是,我无法使用您的solurion,原因有几个:首先,该软件是使用.NET 4.0开发的,我也无法下载Microsoft.Bcl.Async(公司隐私)。不使用async/wait和IProgress例程是否可以执行此操作?非常感谢。@VLT,是的,可以使用
任务。继续使用
而不是
等待
。但是代码会更大,并且您将无法使用线性代码流。我相信,已经尝试了所有方法。它仍然不起作用。在t中有相同的行为task=>超出任务范围而不做任何并行工作的情况非常感谢!但我相信进度(以及IProgress接口都是在.Net 4.5中介绍的)因此我无法访问它们:(@VLT,确实是,我错过了。请检查我的更新以获得替代解决方案。很遗憾,您被限制使用
Microsoft.Bcl.Async
,它有
进度
。请格式化代码,使其真正可读。找到问题的根源(代码上半部分的一个代理使整个过程在另一个线程上运行。因此,调用在另一个线程上创建的
frmWinProg
,最终导致死锁。感谢您的帮助,非常感谢
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication_22487698
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        IEnumerable<int> _data = Enumerable.Range(1, 100);
        Action _cancelWork;

        private void DoWorkItem(
            int[] data,
            int item,
            CancellationToken token,
            IProgress<int> progressReport,
            ParallelLoopState loopState)
        {
            // observe cancellation
            if (token.IsCancellationRequested)
            {
                loopState.Stop();
                return;
            }

            // simulate a work item
            Thread.Sleep(500);

            // update progress
            progressReport.Report(item);
        }

        private async void startButton_Click(object sender, EventArgs e)
        {
            // update the UI
            this.startButton.Enabled = false;
            this.stopButton.Enabled = true;

            try
            {
                // prepare to handle cancellation
                var cts = new CancellationTokenSource();
                var token = cts.Token;

                this._cancelWork = () =>
                {
                    this.stopButton.Enabled = false;
                    cts.Cancel();
                };

                var data = _data.ToArray();
                var total = data.Length;

                // prepare the progress updates
                this.progressBar.Value = 0;
                this.progressBar.Minimum = 0;
                this.progressBar.Maximum = total;

                var progressReport = new Progress<int>((i) =>
                {
                    this.progressBar.Increment(1);
                });

                // offload Parallel.For from the UI thread 
                // as a long-running operation
                await Task.Factory.StartNew(() =>
                {
                    Parallel.For(0, total, (item, loopState) =>
                        DoWorkItem(data, item, token, progressReport, loopState));
                    // observe cancellation
                    token.ThrowIfCancellationRequested();
                }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

            // update the UI
            this.startButton.Enabled = true;
            this.stopButton.Enabled = false;
            this._cancelWork = null;
        }

        private void stopButton_Click(object sender, EventArgs e)
        {
            if (this._cancelWork != null)
                this._cancelWork();
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApplication_22487698
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        IEnumerable<int> _data = Enumerable.Range(1, 100);
        Action _cancelWork;

        private void DoWorkItem(
            int[] data,
            int item,
            CancellationToken token,
            Action<int> progressReport,
            ParallelLoopState loopState)
        {
            // observe cancellation
            if (token.IsCancellationRequested)
            {
                loopState.Stop();
                return;
            }

            // simulate a work item
            Thread.Sleep(500);

            // update progress
            progressReport(item);
        }

        private void startButton_Click(object sender, EventArgs e)
        {
            // update the UI
            this.startButton.Enabled = false;
            this.stopButton.Enabled = true;

            Action enableUI = () =>
            {
                // update the UI
                this.startButton.Enabled = true;
                this.stopButton.Enabled = false;
                this._cancelWork = null;
            };

            Action<Exception> handleError = (ex) =>
            {
                // error reporting
                MessageBox.Show(ex.Message);
            };

            try
            {
                // prepare to handle cancellation
                var cts = new CancellationTokenSource();
                var token = cts.Token;

                this._cancelWork = () =>
                {
                    this.stopButton.Enabled = false;
                    cts.Cancel();
                };

                var data = _data.ToArray();
                var total = data.Length;

                // prepare the progress updates
                this.progressBar.Value = 0;
                this.progressBar.Minimum = 0;
                this.progressBar.Maximum = total;

                var syncConext = SynchronizationContext.Current;

                Action<int> progressReport = (i) =>
                    syncConext.Post(_ => this.progressBar.Increment(1), null);

                // offload Parallel.For from the UI thread 
                // as a long-running operation
                var task = Task.Factory.StartNew(() =>
                {
                    Parallel.For(0, total, (item, loopState) =>
                        DoWorkItem(data, item, token, progressReport, loopState));
                    // observe cancellation
                    token.ThrowIfCancellationRequested();
                }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);

                task.ContinueWith(_ => 
                {
                    try
                    {
                        task.Wait(); // rethrow any error
                    }
                    catch (Exception ex)
                    {
                        while (ex is AggregateException && ex.InnerException != null)
                            ex = ex.InnerException;
                        handleError(ex);
                    }
                    enableUI();
                }, TaskScheduler.FromCurrentSynchronizationContext());
            }
            catch (Exception ex)
            {
                handleError(ex);
                enableUI();
            }
        }

        private void stopButton_Click(object sender, EventArgs e)
        {
            if (this._cancelWork != null)
                this._cancelWork();
        }
    }
}