Question async/await

Lotok

New member
Joined
Feb 5, 2013
Messages
4
Programming Experience
3-5
I am trying to get my head around the changes in .NET 4.5, mainly the async features. To get my head around it I thought i would create a little app for archiving my massive photo collection. I learn best by doing so the application serves a double purpose.


I have read plenty MSDN articles on using async but I dont think I have a good enough understanding of it. My intention was to have each photo at a source folder copied to a destination folder based on it date taken (or created if taken meta data is missing). At the same time renaming it to a standard naming convention and showing the image as it is archived in a picture box. I wanted the application to remain responding during the work, which is where async comes in. Now the app purpose is unimportant, the entire point was getting my head around async.

What actually happens is the app goes unresponsive, archives all the images as intended but the imagebox only shows the final picture. Async is kicking off the file transfer then moving on to the next image, kicking off the transfer then moving on etc etc so i end up with hundreds of open file streams rather than it waiting for each to close.

Any pointers in where I am going wrong would be appreciated

imgMain is the imagebox in the XAML file. The async/await is in the archive method but showing all code as it may be relevant.


using System;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.IO;
namespace PhotoArchive
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private string Source 
        {
            get { return txtSource.Text; }
            set { txtSource.Text = value; }
        }
        private string Destination
        {
            get { return txtDestination.Text; }
            set { txtDestination.Text = value; }
        }

        public MainWindow()
        {
            InitializeComponent();
            
        }
        private void btnBrowseDataSource_Click(object sender, RoutedEventArgs e)
        {
            var dialogue = new FolderBrowserDialog();
            dialogue.ShowDialog();
            Source = dialogue.SelectedPath;
        }
        private void btnBrowseDestination_Click(object sender, RoutedEventArgs e)
        {
            var dialogue = new FolderBrowserDialog();
            dialogue.ShowDialog();
            Destination= dialogue.SelectedPath;
        }
        private void btnSort_Click(object sender, RoutedEventArgs e)
        {
            var files = Directory.GetFiles(Source, "*.*", SearchOption.AllDirectories);
            var result = from i in files
                         where i.ToLower().Contains(".jpg") || i.ToLower().Contains(".jpeg") || i.ToLower().Contains(".png")
                         select i;
            
                             
            foreach (string f in result)
            {
                DateTime dest = GetDateTakenFromImage(f);
                Archive(f, Destination, dest);
            }
           
        }
        private async void Archive(string file, string destination, DateTime taken)
        {
            //Find Destination Path
            var sb = new StringBuilder();
            sb.Append(destination);
            sb.Append("\\");
            sb.Append(taken.ToString("yyyy"));
            sb.Append("\\");
            sb.Append(taken.ToString("MM"));
            sb.Append("\\");
            if (! Directory.Exists(sb.ToString()))
            {
                Directory.CreateDirectory(sb.ToString());
            }
            sb.Append(taken.ToString("dd_MM_yyyy_H_mm_ss_"));
            sb.Append((Directory.GetFiles(destination, "*.*", SearchOption.AllDirectories).Count()));
            string[] extension = file.Split('.');
            sb.Append("." + extension[extension.Length-1]);
            
            using (FileStream fs = File.Open(file, FileMode.Open))
            using (FileStream ds = File.Create(sb.ToString())) 
            {
                await fs.CopyToAsync(ds);
                fs.Close();
                File.Delete(file);
            }
           
            ImgMain.Source = new BitmapImage(new Uri(sb.ToString()));
        }
        //get date info
        private static Regex r = new Regex(":");
        public static DateTime GetDateTakenFromImage(string path)
        {
            using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read))
            {
                using (System.Drawing.Image img = System.Drawing.Image.FromStream(fs, false, false))
                {
                    PropertyItem prop;
                    try
                    {
                        prop = img.GetPropertyItem(36867);
                    }
                    catch (Exception)
                    {
                        prop = img.GetPropertyItem(306);
                    }
                    string dateTaken = r.Replace(Encoding.UTF8.GetString(prop.Value), "-", 2);
                    return DateTime.Parse(dateTaken);
                }
            }

        }
    }
}

 
Solved - The solution was to make the Archive method return a Task, then using the awaits keyword in the button click to await the archive task
 
Back
Top Bottom