C# ProgressBar值正在更改,但WPF上的gui没有更改
我正在尝试实现一个C# ProgressBar值正在更改,但WPF上的gui没有更改,c#,wpf,C#,Wpf,我正在尝试实现一个ProgressBar,它将在文件传输期间显示 文件传输由BackgroundWorker完成 只是为了检查功能,我尝试从主线程取得进展,但什么也没有发生 守则: myProgressBar.Minimum = 0; myProgressBar.Maximum = numOfPackets; 这是后台工作代码 然后: myProgressBar.IsEnabled = true; for (int i = 0; i < buff.Length; i++) {
ProgressBar
,它将在文件传输期间显示
文件传输由BackgroundWorker
完成
只是为了检查功能,我尝试从主线程取得进展,但什么也没有发生
守则:
myProgressBar.Minimum = 0;
myProgressBar.Maximum = numOfPackets;
这是后台工作代码
然后:
myProgressBar.IsEnabled = true;
for (int i = 0; i < buff.Length; i++)
{
myProgressBar.Value = i;
myProgressBar.UpdateDefaultStyle();
}
myProgressBar.IsEnabled=true;
for(int i=0;i
为什么什么都不改变?对于wpf,您可以使用:
this.Dispacher.BeginInvoke(new Action(()=> { for(int i...)...; }));
在后台线程上执行IO或文件传输是非常糟糕的,因为在文件传输或IO操作期间,CPU没有被使用,所以后台线程除了等待IO完成之外什么都不做,而您正在浪费一个线程,这反过来又会导致内存浪费。另一个缺点是,您的UI将变得非常糟糕文件传输的无响应需要相当长的时间,即使您是在后台线程上进行的 我可以继续写在后台线程上进行IO工作的缺点,但您应该请求一份关于在后台线程中异步执行IO的文档。净。 后台线程用于CPU密集型工作,如一些涉及CPU的繁重计算 您应该使用异步IO。使用异步和等待。请阅读异步IO。 我有一个示例,演示了您使用progressbar和响应UI的纯异步IO所做的一切。我明天写 ** 下面是异步io文件传输代码,假设所有文件的大小都相同,以便进行进度更新 下面提到的代码可以工作,即使在传输文件时移动窗口,应用程序也不会挂起。 ** main window.xaml
<Window x:Class="asyncawait.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="514" Width="674">
<Grid Margin="0,0,0,4">
<ScrollViewer Name="scrv_Log" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" HorizontalAlignment="Left" Width="397" Margin="33,61,0,67">
<ListBox VirtualizingPanel.VirtualizationMode="Recycling" ItemsSource="{Binding Datas,Mode=OneWay}" Background="White" Foreground="Red"/>
</ScrollViewer>
<TextBlock Height="40" Width="70" FontSize="10" Foreground="Green" Text="{Binding FileCounter,Mode=OneWay}" Margin="540,281,56,158"></TextBlock>
<Button Foreground="Black" IsEnabled="{Binding IsButtonEnabled}" Click="Button_Click" Height="40" Width="40" RenderTransformOrigin="4.65,0.425" Margin="540,210,86,229"></Button>
<ProgressBar Value="{Binding Progressvalue,Mode=OneWay}" Name="prg" Foreground="Green" Height="20" Width="600" Margin="23,453,44.2,7"></ProgressBar>
<Label Content="{Binding ElementName=prg,Path=Value}" ContentStringFormat="{}{0}%" Height="25" Margin="253,0,295.2,22" VerticalContentAlignment="Center" VerticalAlignment="Bottom"/>
<TextBox Background='AliceBlue' HorizontalAlignment="Left" Height="23" Margin="525,109,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="97"/>
</Grid>
</Window>
****下面是执行异步IO的代码**
public partial class MainWindow: Window,INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
public double Progressvalue
{
get
{
return _Progressvalue;
}
set
{
if(value!=_Progressvalue)
{
_Progressvalue=value;
OnPropertyChanged();
}
}
}
private Double _Progressvalue=0;
private bool _IsEnabled=true;
public Boolean IsButtonEnabled {
get
{
return _IsEnabled;
}
set
{
if(value!=_IsEnabled)
{
_IsEnabled = value;
OnPropertyChanged();
}
}
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
IsButtonEnabled = false;
await AsyncTransferFiles();
IsButtonEnabled = true;
scrv_Log.ScrollToBottom();
}
private String fileCounter;
public String FileCounter
{
get
{ return fileCounter; }
set
{
if (value != fileCounter)
{
fileCounter = value;
OnPropertyChanged();
}
}
}
private ObservableCollection<String> _Datas = new ObservableCollection<string>();
public ObservableCollection<String> Datas
{
get
{
return _Datas;
}
}
private async Task AsyncTransferFiles()
{
var fileNames = Directory.GetFiles("C:\\Data1").ToList();
int totalCount = fileNames.Count;
pr = (double)1 / totalCount;
int counter = 0;
var progress = new Progress<double>();
progress.ProgressChanged += (sender, e) =>
{
Progressvalue = Double.Parse(e.ToString());
};
foreach (var fileName in fileNames)
{
await (CopyFileAsync(fileName, "C:\\GradebookTemp1\\" + fileName.Split('\\')[2], progress, ++counter));
}
}
double pr = 0.0;
public async Task CopyFileAsync(string sourcePath, string destinationPath,IProgress<double> progress ,int fileCounter)
{
using (Stream source = File.Open(sourcePath,FileMode.Open))
{
using (Stream destination = File.Create(destinationPath))
{
await source.CopyToAsync(destination);
progress.Report((int)(pr*fileCounter*100));
FileCounter = fileCounter.ToString();
Datas.Add("Copied File: " + sourcePath);
scrv_Log.ScrollToBottom();
}
}
}
private void EnableButton()
{
IsButtonEnabled = true;
}
private void OnPropertyChanged([CallerMemberName] String propertyName=null)
{
var handler = PropertyChanged;
if(null!=handler)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
public分部类主窗口:窗口,INotifyPropertyChanged
{
公共主窗口()
{
初始化组件();
this.DataContext=this;
}
公共双重价值
{
得到
{
返回值;
}
设置
{
如果(值!=\u进度值)
{
_价值=价值;
OnPropertyChanged();
}
}
}
私有双精度_Progressvalue=0;
private bool _IsEnabled=true;
公共布尔值IsButtonEnabled{
得到
{
返回已启用;
}
设置
{
如果(值!=\u已启用)
{
_IsEnabled=值;
OnPropertyChanged();
}
}
}
专用异步无效按钮\u单击(对象发送方,路由目标)
{
IsButtonneEnabled=错误;
等待AsyncTransferFiles();
IsButtonneEnabled=真;
scrv_Log.ScrollToBottom();
}
私有字符串文件计数器;
公共字符串文件计数器
{
得到
{返回文件计数器;}
设置
{
if(值!=文件计数器)
{
fileCounter=值;
OnPropertyChanged();
}
}
}
私有ObservableCollection_data=新ObservableCollection();
公共可观测收集数据
{
得到
{
返回_数据;
}
}
专用异步任务AsyncTransferFiles()
{
var fileNames=Directory.GetFiles(“C:\\Data1”).ToList();
int totalCount=文件名.Count;
pr=(双)1/总计数;
int计数器=0;
var progress=新进度();
progress.ProgressChanged+=(发件人,e)=>
{
Progressvalue=Double.Parse(例如ToString());
};
foreach(文件名中的var文件名)
{
等待(CopyFileAsync(文件名,“C:\\GradebookTemp1\\”+文件名.Split('\\')[2],进度,++计数器));
}
}
双pr=0.0;
公共异步任务CopyFileAsync(字符串sourcePath、字符串destinationPath、IProgress progress、int fileCounter)
{
使用(Stream source=File.Open(sourcePath,FileMode.Open))
{
使用(streamdestination=File.Create(destinationPath))
{
等待源。CopyToAsync(目标);
进度报告((int)(pr*fileCounter*100));
FileCounter=FileCounter.ToString();
添加(“复制的文件:”+sourcePath);
scrv_Log.ScrollToBottom();
}
}
}
私有void EnableButton()
{
IsButtonneEnabled=真;
}
私有void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
var handler=PropertyChanged;
if(null!=处理程序)
{
处理程序(这是新的PropertyChangedEventArgs(propertyName));
}
}
公共事件属性更改事件处理程序属性更改;
}
该解决方案曾经对我有效:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button_Click(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 100; i++)
{
progBar.Value = i;
progBar.Refresh();
Thread.Sleep(10);
}
}
}
public static class ExtensionMethods
{
private static Action EmptyDelegate = delegate () { };
public static void Refresh(this UIElement uiElement)
{
uiElement.Dispatcher.Invoke(DispatcherPriority.Render, EmptyDelegate);
}
}
公共部分类主窗口:窗口
{
公共主窗口()
{
初始化组件();
}
私有无效按钮\u单击(对象发送者,路由目标e)
{
对于(int i=0;i<100;i++)
{
progBar.Value=i;
progBar.Refresh();
睡眠(10);
}
}
}
公共sta
<Grid>
<ProgressBar x:Name="progBar" HorizontalAlignment="Left" Height="10" Margin="116,175,0,0" VerticalAlignment="Top" Width="100"/>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="156,51,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
myProgressBar.Refresh();