0

Here is the Code I already have.

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);
            }
        }
    }
}

What I would like to be able to do is call installAndLog() function without freezing the UI. I am very new to C# Multi threaded coding. I would be doing file copies in the installAndLog() function and would like to be able to see what is going on in realtime. The csv file structure is as follows:

netbook1,file1
netbook2,file2
etc....

Thanks for any help.

BenMorel
  • 34,448
  • 50
  • 182
  • 322

1 Answers1

0

You need to remove the ui variable as it is synchronizing the task onto the ui thread causing the ui to lockup.

Then you need to wrap all calls to ui controls inside a invokeRequired pattern. See this for details link

Edit: Giving this is not winforms, and if you really want to be counter productive, you can do the same with the Dispatcher

You should seriosly take a look at MVVM pattern instead:

Community
  • 1
  • 1
Nickolai Nielsen
  • 932
  • 6
  • 19
  • is invokeRequired windows forms not wpf? – user2917005 Oct 24 '13 at 21:51
  • you did not state anywhere what technology you where using, and the approach you are using looks like winforms. In WPF you would use the MVVM pattern and databindings. The databinding would handle the threading issue for updating a control from another thread. – Nickolai Nielsen Oct 25 '13 at 07:24