如何使写入文本框的功能工作?(不冻结用户界面)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....

感谢您的任何帮助。

如何使写入文本框的功能工作?(不冻结用户界面)C# .NET 4 TPL.

您需要删除 ui 变量,因为它正在将任务同步到 ui 线程上,从而导致 ui 锁定。

然后,您需要将对 ui 控件的所有调用包装在 invokeRequired 模式中。有关详细信息链接,请参阅此链接

编辑:给出这个不是赢形,如果你真的想适得其反,你可以用调度程序做同样的事情

你应该仔细看看 MVVM 模式:

  • WPF/MVVM 快速入门教程
  • 具有模型-视图-视图模型设计模式的 WPF 应用