C# 使用后台工作程序将文本文件插入列表框WPF
当我在循环中添加这行代码时C# 使用后台工作程序将文本文件插入列表框WPF,c#,wpf,data-binding,C#,Wpf,Data Binding,当我在循环中添加这行代码时 myCollection.Add(new FetchData(line)); 它抛出 此类型的CollectionView不支持从不同于Dispatcher线程的线程更改其SourceCollection 我也尝试过使用这个,但没有成功: mqttUpload.ItemsSource = MyList; 进度条会更新,我也可以打印行,唯一的问题是我无法将数据添加到列表框 这是我的数据在txt文件中的样子,该文件包含3500行。 这是我试过的 public pa
myCollection.Add(new FetchData(line));
它抛出
此类型的CollectionView不支持从不同于Dispatcher线程的线程更改其SourceCollection
我也尝试过使用这个,但没有成功:
mqttUpload.ItemsSource = MyList;
进度条会更新,我也可以打印行,唯一的问题是我无法将数据添加到列表框
这是我的数据在txt文件中的样子,该文件包含3500行。
这是我试过的
public partial class UserControl2 : UserControl
{
public static List<string> Mylist = new List<string>();
ObservableCollection<FetchData> myCollection = new ObservableCollection<FetchData>();
public UserControl2()
{
InitializeComponent();
mqttUpload.ItemsSource = myCollection;
backgroundWorker1.DoWork += backgroundWorker1_DoWork;
backgroundWorker1.ProgressChanged +=backgroundWorker1_ProgressChanged;
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.RunWorkerCompleted += jobfinish;
}
public static UserControl2 uploadData;
BackgroundWorker backgroundWorker1 = new BackgroundWorker();
public static string FilePath = "";
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
var files = File.ReadAllLines(FilePath);
for (int i = 0; i < files.Length; i++)
{
var line = files[i];
Mylist.Add(line);
int percentage = (int)((i / (double)files.Length) * 100.0);
backgroundWorker1.ReportProgress(percentage);
Console.WriteLine(line);
}
}
public void jobfinish(object sender, RunWorkerCompletedEventArgs e)
{
Console.WriteLine( "finish");
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)// progress change
{
progressBar1.Value = e.ProgressPercentage;
}
}
下面是XAML代码
<ListBox Margin="10,64,0,-434" Grid.Column="2" Name="mqttUpload"
Padding="20,0,0,0" Background="#18191A" Foreground="#F5980C" Grid.Row="2" />
我的目标是在显示进度条的同时逐行读取数据,最后在列表框中显示数据
这就是数据在列表框中的显示方式。在这幅图中,我正在从数据库中读取数据。我想实现相同的,但从txt文件读取。
为什么不等到作业完成呢 您可以通过ReportsProgress发送数据
一次更新一行UI会带来很大的开销。我将使用异步文件IO并读取前100行,然后读取整个文件。最重要的规则:只能从GUI(主)线程触摸GUI 您的
Mylist.Add(行)代码>违反了这条规则
您也可以使用进度事件:
backgroundWorker1.ReportProgress(percentage, line);
然后
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)// progress change
{
progressBar1.Value = e.ProgressPercentage;
string line = (string) e.State;
Mylist.Add(line); // ok, this runs on the main thread
}
我以前也能将数据输入MyList,唯一的问题是我不能将数据添加到列表框中。我相信这将通过使用ObservableCollection来实现,我取代了Mylist.Add(line);添加(新的FetchData(行));使用您的代码,我的gui冻结。也不起作用。那FetchData
不可能改变任何东西。我的代码不应该冻结,肯定还有一些你没有发布的东西。但这里最好的事情是避免这种情况:没有用户可以或想要读取3500行。你的GUI不是你的数据层。我不介意等到作业完成,但最后它应该会在GUI的列表框中显示数据。然后在jobFinished中执行。这听起来像是一个XY问题。真正的问题是,需要完成的99.9%的实际CPU工作必须发生在UI线程上:即呈现列表视图中显示行的所有控件。您无法真正显示UI呈现工作的进度条。您最好的选择是虚拟化。您应该简单地避免进行所有不必要的渲染,这样就不需要进度条,因为您的UI会立即加载
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)// progress change
{
progressBar1.Value = e.ProgressPercentage;
string line = (string) e.State;
Mylist.Add(line); // ok, this runs on the main thread
}