如何使用C#中的任务更新进度条? [英] How to update progressbar using tasks in C#?

查看:109
本文介绍了如何使用C#中的任务更新进度条?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我想显示Marquee样式进度条。

我有一个表格,上面有一个包含按钮的工具栏。

点击该按钮,我打电话给网络服务。

直到webservice调用返回我想显示模式对话框上的Marquee进度条。



如何通过Tasks实现它( TPL)或两种方式?

请提供代码示例。



我尝试过的方法:



 CancellationToken cancelToken =  new  CancellationToken(); 
任务task1 = Task.Factory.StartNew(()= >
{
BaseParameters.ErrorBag.Clear();
if (ESignatureService.SignDocuments(documentIds,GlobalVariables.oLoginRO.PersonalSchluessel))
SaveAndPopulateDocuments();
breakFlag = false ;
},cancelToken)
.ContinueWith(t = >
{
while (oi1ProgressStatus.PercentageComplete < 100
{
oi1ProgressStatus.PercentageComplete ++;
Thread.Sleep( 100 );
if (oi1ProgressStatus.PercentageComplete == 100
{
oi1ProgressStatus.PercentageComplete = 0 ;
}
}
},TaskScheduler.Default);
Task.WaitAny(task1);





我试过这种方式,但是我收到以下错误。



为不能作为另一个线程上的控件的父节点的线程创建的控件。

解决方案

ProgressBar控件 [ ^ ]内置支持显示不确定的进度 - 只需设置样式属性 [ ^ ]到 ProgressBarStyle.Marquee

 oi1ProgressStatus.Style = ProgressBarStyle.Marquee; 

await Task.Run(()= >
{
BaseParameters.ErrorBag.Clear();
if (ESignatureService.SignDocuments(documentIds,GlobalVariables.oLoginRO.PersonalSchluessel))
SaveAndPopulateDocuments();

breakFlag = false ;
});

oi1ProgressStatus.Style = ProgressBarStyle.Blocks;



注意:您无法从后台更新UI元素线程,因此您需要使用调用将更新推送回UI线程。如果在UI线程上使用 Task.WaitAny ,则会阻止 Invoke 方法,并导致死锁。使用 async / 等待,这将在后台任务运行时保持UI线程响应。



如果您不能使用 async / 等待,那么请使用 BackgroundWorker [ ^ ]执行任务。


这是基本想法,您可能需要根据自己的需要进行调整。不要尝试自己的军事线索,这只需要遗留代码。 async await 关键字提供了足够的抽象,你不必这样做。

 < span class =code-comment> //  这是按钮点击事件处理程序 
// 注意异步修饰符
private async void ReadWebPageEventHandlerAsync( object sender,RoutedEventArgs e)
{
string text;
// ***插入代码以启动进度条***
使用 var client = new HttpClient())
{
// 启动所需的异步进程,在这种情况下它是GetStringAsync
text = await client.GetStringAsync( @ http://www.codeproject.com/);
}

// 控件在GetStringAsync完成时返回,
// **插入代码以停止进度条**
// 使用等待调用的结果执行某些操作
// 此处将TextBox文本设置为结果
.textBox.Text = text;
}


In my project I want to show the Marquee style progress bar.
where I had a form on which there is a toolbar containing a button.
On the click of that button I call a webservice.
Till webservice call returns I want to show the Marquee progress bar which is on modal dialog.

How I can achieve it by Tasks(TPL) or either way?
Please provide the code sample for it.

What I have tried:

CancellationToken cancelToken = new CancellationToken();
                Task task1 = Task.Factory.StartNew(() =>
                {
                    BaseParameters.ErrorBag.Clear();
                    if (ESignatureService.SignDocuments(documentIds, GlobalVariables.oLoginRO.PersonalSchluessel))
                        SaveAndPopulateDocuments();
                    breakFlag = false;
                }, cancelToken)
                .ContinueWith(t =>
                {
                    while (oi1ProgressStatus.PercentageComplete < 100)
                    {
                        oi1ProgressStatus.PercentageComplete++;
                        Thread.Sleep(100);
                        if (oi1ProgressStatus.PercentageComplete == 100)
                        {
                            oi1ProgressStatus.PercentageComplete = 0;
                        }
                    }
                }, TaskScheduler.Default);
                Task.WaitAny(task1);



I tried by this way but I am getting the following error.

"Controls that were created for a thread that can not be the parent of a control on a different thread."

解决方案

The ProgressBar control[^] has built-in support for showing indeterminate progress - just set the Style property[^] to ProgressBarStyle.Marquee:

oi1ProgressStatus.Style = ProgressBarStyle.Marquee;

await Task.Run(() =>
{
    BaseParameters.ErrorBag.Clear();
    if (ESignatureService.SignDocuments(documentIds, GlobalVariables.oLoginRO.PersonalSchluessel))
        SaveAndPopulateDocuments();
    
    breakFlag = false;
});

oi1ProgressStatus.Style = ProgressBarStyle.Blocks;


NB: You can't update UI elements from a background thread, so you'll need to use Invoke to push the updates back onto the UI thread. If you use Task.WaitAny on the UI thread, you'll block the Invoke method, and cause a deadlock. Use async / await instead, which will keep the UI thread responsive whilst your background task is running.

If you can't use async / await, then use a BackgroundWorker[^] to perform your task.


Here's the basic idea, you may have to adapt it to your needs. Don't try to martial threads yourself, that is only necessary with legacy code. The async await keywords provide sufficient abstraction for you not to have to do that.

//This is the button click event handler
//note the async modifier
private async void ReadWebPageEventHandlerAsync(object sender, RoutedEventArgs e)
        {
            string text ;
			//***insert code to start the progress bar here***
            using (var client = new HttpClient())
            {
			     //start the required async process,  in this case it's GetStringAsync
                text = await client.GetStringAsync(@"http://www.codeproject.com/");
            }

            //control returns here when GetStringAsync finishes, 
			//**insert code to stop the progress bar here**
            //Do something with the result from the await call
             // here a TextBox text is set to the result
            this.textBox.Text = text;
        }


这篇关于如何使用C#中的任务更新进度条?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆