Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.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# ProgressBar从另一个线程更新_C#_Wpf_Multithreading_Progress Bar_Async Await - Fatal编程技术网

C# ProgressBar从另一个线程更新

C# ProgressBar从另一个线程更新,c#,wpf,multithreading,progress-bar,async-await,C#,Wpf,Multithreading,Progress Bar,Async Await,我知道这个问题以前被问过100次,但我读到的所有答案对我都不起作用。所以,我会试试运气,再问一次 我有一个滑块,它在ValueChanged事件上调用一个方法。 在这个方法中,我做了一些需要时间的事情,我希望在这段时间内,用户将看到一个“正在工作的”ProgressBar(IsIndeterminate=true) 不幸的是,在所有方法循环完成之前,我无法成功地使ProgressBar开始工作(在UI中)。 我尝试了线程、BackgroundWorker和async任务,但没有成功 我做错了什么

我知道这个问题以前被问过100次,但我读到的所有答案对我都不起作用。所以,我会试试运气,再问一次

我有一个
滑块
,它在
ValueChanged
事件上调用一个方法。 在这个方法中,我做了一些需要时间的事情,我希望在这段时间内,用户将看到一个“正在工作的”
ProgressBar
IsIndeterminate=true

不幸的是,在所有方法循环完成之前,我无法成功地使
ProgressBar
开始工作(在UI中)。 我尝试了线程、
BackgroundWorker
async
任务,但没有成功

我做错了什么

方法如下:

    private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e){
        WorkingBar.IsIndeterminate = true;      //change the progressBar          
        SqlAThread = new Thread(SqlAStart);     
        SqlAThread.Start();
    }

与其把整个漫长的过程都打印出来,不如请大家看看我对StackOverflow问题的回答。它演示了如何正确使用
BackgroundWorker
对象来更新
ProgressBar
的进度值


您可能还想查看MSDN上的页面以获取更详细的信息。

Slider\u ValueChanged
中,您可以开始新的步骤来运行耗时的
SqlAStart()
方法,但
SqlAStart
会立即将工作推回到UI线程(通过
Dispatcher.Invoke()
)。因此,您的UI挂起,在工作完成之前,您不会看到任何
ProgressBar
进度

SqlAStart
中,仅在需要更新进度条的位置执行
Dispatcher.Invoke()

private void SqlAStart()
{
    ServerThread = new Thread(HttpSrv.listen);
    ServerThread.Start();
    ...

    this.Dispatcher.Invoke((Action)(() => {
        WorkingBar.Value = ...                
    }));

    ....
}

这很容易使用
IProgress

private async void Slider\u值已更改(对象发送方,RoutedPropertyChangedEventArgs e)
{
如果(State.Value>0)
{
变量进度=新进度(值=>
{
WorkingBar.IsIndeterminate=(值==null);
if(值!=null)
工作条.Value=Value.Value;
});
等待任务。运行(()=>doWork(progress));
运行(SqlAStart);
}
...
}
私有void SqlAStart(IProgress进程)
{
ServerTask=Task.Run(HttpSrv.listen);
...
}
私人无效工作(i进度)
{
如果(进度!=null)
进度报告(空);
...
}

请注意,在现代应用程序中,您应该(几乎)永远不要使用
Dispatcher
Thread
BackgroundWorker

doWork方法中的Dispatcher语法是您想要使用的,您想要将您想要执行的操作推送到UI线程中,此时,您似乎正在更改进度条的属性,也可以使用此语法更新进度条。@JMK此属性是我要更改的,当此属性为“true”时,进度条应处于“工作”模式(我认为…?)。实际上,它是有效的,但只有当所有的循环都完成时=/你好@sheridan我试过你的代码(实际上这是我第一次尝试)我理解你的示例,但不要在我的代码中使用它。@Yaron,暂时忽略你的代码。将该示例代码放入新的WPF应用程序或项目中,并使其正常工作。然后通过一个工作示例进行实验,您应该能够将其应用到您的代码中。但是现在,当我尝试在我的代码中使用它时,它对我不起作用。我尝试了你的代码(顺便说一句,谢谢,我以前不知道IProgress),但是,在SqlAstart完成后,UI更新…@Yaron该方法在做什么?如果它正在调用UI线程并阻塞它一段时间,那么很明显,在它进行的过程中,没有其他东西可以更新。
private void SqlAStart()
{
    ServerThread = new Thread(HttpSrv.listen);
    ServerThread.Start();
    ...

    this.Dispatcher.Invoke((Action)(() => {
        WorkingBar.Value = ...                
    }));

    ....
}
private async void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
  if (State.Value > 0)
  {
    var progress = new Progress<int?>(value =>
    {
      WorkingBar.IsIndeterminate = (value == null);
      if (value != null)
        WorkingBar.Value = value.Value;
    });
    await Task.Run(() => doWork(progress));
    Task.Run(SqlAStart);
  }
  ...
}

private void SqlAStart(IProgress<int?> progress)
{
  ServerTask = Task.Run(HttpSrv.listen);
  ...
}

private void doWork(IProgress<int?> progress)
{
  if (progress != null)
    progress.Report(null);
  ...
}