如何使写入文本框的功能工作?(不冻结用户界面)C# .NET 4 TPL.
本文关键字:用户界面 冻结 TPL NET 文本 何使写 工作 功能 | 更新日期: 2023-09-27 18:36:50
这是我已有的代码。
using System;
using System.IO;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
using System.Diagnostics;
namespace ListInstaller
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();
public MainWindow()
{
InitializeComponent();
}
private void btnTarget_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.FolderBrowserDialog fBD = new System.Windows.Forms.FolderBrowserDialog();
fBD.RootFolder = Environment.SpecialFolder.Desktop;
fBD.ShowNewFolderButton = true;
fBD.Description = "Select the backup store folder.";
System.Windows.Forms.DialogResult result = fBD.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
tbTarget.Text = fBD.SelectedPath;
}
}
private void btnDestination_Click(object sender, RoutedEventArgs e)
{
System.Windows.Forms.FolderBrowserDialog fBD = new System.Windows.Forms.FolderBrowserDialog();
fBD.RootFolder = Environment.SpecialFolder.Desktop;
fBD.ShowNewFolderButton = true;
fBD.Description = "Select the backup store folder.";
System.Windows.Forms.DialogResult result = fBD.ShowDialog();
if (result == System.Windows.Forms.DialogResult.OK)
{
tbDestination.Text = fBD.SelectedPath;
}
}
private void btnCSVSource_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog opFD = new Microsoft.Win32.OpenFileDialog();
opFD.DefaultExt = ".csv";
opFD.Filter = "CSV Files (*.csv)|*.csv";
opFD.InitialDirectory = "D:''";
Nullable<bool> result = opFD.ShowDialog();
if (result == true)
{
string filename = opFD.FileName;
tbCSVSource.Text = filename;
}
}
private void cbBackup_Checked(object sender, RoutedEventArgs e)
{
btnDestination.Visibility = Visibility.Visible;
lblDestination.Visibility = Visibility.Visible;
tbDestination.Visibility = Visibility.Visible;
tbMainLog.AppendText("'nSwitching to Back Up Mode. @ " + DateTime.Now);
}
private void cbBackup_Unchecked(object sender, RoutedEventArgs e)
{
btnDestination.Visibility = Visibility.Hidden;
lblDestination.Visibility = Visibility.Hidden;
tbDestination.Visibility = Visibility.Hidden;
tbMainLog.AppendText("'nSwitching to Normal Mode. @ " + DateTime.Now);
}
private void List_Installer_Loaded(object sender, RoutedEventArgs e)
{
DateTime currTime = DateTime.Now;
tbMainLog.Text = "Started at " + currTime;
}
private void tbMainLog_TextChanged(object sender, TextChangedEventArgs e)
{
tbMainLog.ScrollToEnd();
}
private void btnInstall_Click(object sender, RoutedEventArgs e)
{
Stopwatch timer = Stopwatch.StartNew();
List<Task> tasks = new List<Task>();
BlockingCollection<string[]> data = new BlockingCollection<string[]>();
Task install = Task.Factory.StartNew(() => installAndLog(data));
string filepath = tbCSVSource.Text;
Task parse = Task.Factory.StartNew(() =>
{
CSVParser csvpParser = new CSVParser(filepath);
data = csvpParser.parsedDate();
data.CompleteAdding();
});
tasks.Add(parse);
Task.Factory.ContinueWhenAll(tasks.ToArray(),
result =>
{
Int64 time = timer.ElapsedMilliseconds;
//foreach(string[] row in data.GetConsumingEnumerable())
//{
// string netbookName = row[0];
// string boxNumber = row[1];
// tbMainLog.Text += "'n";
// tbMainLog.Text += "Netbook: " + netbookName + "'t";
// tbMainLog.Text += "Box Number: " + boxNumber + "'t";
//}
tbMainLog.Text += "'nTime taken: ";
tbMainLog.Text += time.ToString() + "milliseconds";
}, CancellationToken.None, TaskContinuationOptions.None, ui);
}
private void installAndLog(BlockingCollection<string[]> data)
{
foreach (string[] row in data.GetConsumingEnumerable())
{
string netbookName = row[0];
string boxNumber = row[1];
Task.Factory.StartNew(new Action(() =>
{
tbMainLog.Text += "'n";
tbMainLog.Text += "Netbook: " + netbookName + "'t";
tbMainLog.Text += "Box Number: " + boxNumber + "'t";
tbErrors.AppendText(boxNumber + " -- " + netbookName + " File Not Found.'n");
}), CancellationToken.None, TaskCreationOptions.None, ui);
}
}
}
}
我希望能够做的是调用installAndLog()函数而不冻结用户界面。我对 C# 多线程编码非常陌生。我将在installAndLog()函数中进行文件复制,并希望能够实时查看正在发生的事情。csv 文件结构如下:
netbook1,file1
netbook2,file2
etc....
感谢您的任何帮助。
您需要删除 ui 变量,因为它正在将任务同步到 ui 线程上,从而导致 ui 锁定。
然后,您需要将对 ui 控件的所有调用包装在 invokeRequired 模式中。有关详细信息链接,请参阅此链接
编辑:给出这个不是赢形,如果你真的想适得其反,你可以用调度程序做同样的事情
你应该仔细看看 MVVM 模式:
- WPF/MVVM 快速入门教程
- 具有模型-视图-视图模型设计模式的 WPF 应用