我想讓我的頭在.NET 4.5中的變化,主要是異步功能。爲了解決這個問題,我想我會創建一個應用程序來歸檔我的海量照片集。我通過這樣做最好地學習了這個應用程序,它有兩個目的。C#異步文件傳輸 - 在繼續循環之前等待
我已經閱讀了大量關於使用異步的MSDN文章,但我不認爲我有足夠的理解它(因爲它不工作)。我的意圖是將源文件夾中的每張照片根據其拍攝日期複製到目標文件夾(或者如果採用元數據丟失,則創建)。同時將其重命名爲標準命名約定,並在圖像存檔在圖像框中時顯示圖像。我希望應用程序在工作期間保持響應,這是異步進入的地方。現在應用程序的目的並不重要,整個過程讓我的頭腦變得異常。
實際發生的情況是應用程序無響應,將所有圖像歸檔爲預期,但圖像框僅顯示最終圖像。異步正在開始文件傳輸,然後移動到下一個圖像,開始傳輸然後繼續等等等等,所以我最終成百上千的開放文件流,而不是等待每個關閉。
任何指針在哪裏我錯了將不勝感激。我對使用Tasks的理解是shakey,返回任務有什麼用途?
imgMain是XAML文件中的圖像框。異步/等待處於歸檔方法中,但顯示所有代碼可能相關。
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);
}
}
}
}
}
我不是專門研究.Net 4.5的新異步/等待功能的專家,但有一點非常重要,那就是您異步運行的唯一一件事是文件副本。雖然有更好的指導,但我相信你會得到一些有用的答案。 –
@DanielKelley你還想要異步運行嗎? – svick
@svick根據你的答案 - 存檔中的所有內容。除了'等待'fs.CopyToAsync'之外,其他所有事情都在捆綁UI線程。 –