【发布时间】:2014-06-07 22:28:07
【问题描述】:
我有一个 Windows 窗体程序 (**VS 2010 .NET 4 **),它递归地检测目录的文件夹和子文件夹并优化文件。
我通过任务库来做到这一点,并有一个显示项目进度的进度条和显示当前文件的进度条附近的标签。
我有一个用于此目的的 SetText(string text) 方法和委托 (delegate void SetTextCallback(string text);)。当我想在进程结束时显示一个消息框时,我认为它死锁了。但是当我在 button6_Click 中不使用task.Wait(); 时,一切正常,UI 不会挂起。
这是我的代码:
public partial class Form1 : Form
{
int MaxFileCounter = 0;
static int FileCounter = 0;
delegate void SetTextCallback(string text);
delegate void SetProgressCallback(int i);
private void button6_Click(object sender, EventArgs e)
{
Task task = Task.Factory.StartNew(() =>
{
editFiles(txtFilePath.Text);
});
task.Wait();
MessageBox.Show("finished");
}
private void editFiles(string directoryPath)
{
try
{
//DirectoryInfo dirInfo = new DirectoryInfo(txtFilePath.Text);
DirectoryInfo dirInfo = new DirectoryInfo(directoryPath);
//string[] extensionArray = { ".jpg", ".png", ".gif" ,".jpeg"};
string[] extensionArray = txtExtensionList.Text.Split(';');
HashSet<string> allowedExtensions = new HashSet<string>(extensionArray, StringComparer.OrdinalIgnoreCase);
FileInfo[] files = Array.FindAll(dirInfo.GetFiles(), f => allowedExtensions.Contains(f.Extension));
writeFiles(files);
foreach (DirectoryInfo dir in dirInfo.GetDirectories())
{
editFiles(dir.FullName);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void writeFiles(FileInfo[] files)
{
try
{
foreach (FileInfo fileinfo in files)
{
MemoryStream mo;
using (Image image = Image.FromFile(fileinfo.FullName))
{
SetText(fileinfo.FullName);
FileCounter++;
SetProgress(FileCounter * 100 / MaxFileCounter);
mo = (MemoryStream)optimizeImage(image, int.Parse(txtPercent.Text));
}
byte[] bt = new byte[mo.Length];
mo.Read(bt, 0, bt.Length);
mo.Flush();
mo.Close();
string fullpath = fileinfo.FullName;
File.WriteAllBytes(fullpath, bt);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void SetText(string text)
{
// InvokeRequired required compares the thread ID of the
// calling thread to the thread ID of the creating thread.
// If these threads are different, it returns true.
if (lblFileName.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.lblFileName.Text = text;
}
}
private void SetProgress(int i)
{
if (progressBar1.InvokeRequired)
{
SetProgressCallback p = new SetProgressCallback(SetProgress);
this.Invoke(p, new object[] { i });
}
else
{
this.progressBar1.Value = i;
}
}
}
我该如何处理?
【问题讨论】:
-
“我该如何处理?” - 删除
task.Wait();。它在错误的时刻做错了事。 -
我知道如果我删除它,它会起作用。所以我应该在工作完成后什么时候宣布用户?何时处理大量文件?
-
@Hamed_gibago
starting a task and wait for it to finish和running the code(editFiles) in the UI thread之间没有区别。在这两种情况下,用户界面都会无响应。 -
让 EditFiles 知道它的递归深度,并在顶层完成时引发一个事件。
-
我该怎么做?
标签: c# task-parallel-library deadlock invoke