C# Winforms:避免冻结应用程序
我在“大”文件上做了一些操作(大约4Mb) 我这样做: 1.从目录中获取所有文件并将其放置在IList MyInfoClass中,该类具有以下属性:名称、扩展名、完整路径、creationDate、contentPart 2.我执行Linq查询只获取一些扩展类型。 3.我循环Linq查询结果,对于每个查询结果,我打开文件,执行一些操作(获取值),并将结果放入MyFileIno.ContentPart 仅供参考:30个文件,这是一个14秒的操作 这就是工作 问题是,当我从UI运行我的库时,当我单击按钮时,窗口在操作期间冻结。我想:C# Winforms:避免冻结应用程序,c#,winforms,performance,C#,Winforms,Performance,我在“大”文件上做了一些操作(大约4Mb) 我这样做: 1.从目录中获取所有文件并将其放置在IList MyInfoClass中,该类具有以下属性:名称、扩展名、完整路径、creationDate、contentPart 2.我执行Linq查询只获取一些扩展类型。 3.我循环Linq查询结果,对于每个查询结果,我打开文件,执行一些操作(获取值),并将结果放入MyFileIno.ContentPart 仅供参考:30个文件,这是一个14秒的操作 这就是工作 问题是,当我从UI运行我的库时,当我单击
公共类文件管理器
{
公共字符串CurrentFileName{get;set;}
公共无效验证(字符串路径)
{
IList listFile=GetListFile(路径);
foreach(列表文件中的信息文件项)
{
CurrentFileName=item.Name;
.....
}
}
}
私有无效按钮1\u单击(对象发送者,事件参数e)
{
var worker=新的BackgroundWorker();
worker.DoWork+=(s,args)=>
{
整数百分比进展=6;
FileManager FileManager=newfilemanager();
fileManager.Validation(@“C:…”);
((BackgroundWorker)s).ReportProgress(percentProgress,fileManager.CurrentFileName);
};
worker.ProgressChanged+=(s,args)=>
{
var currentFilename=(字符串)args.UserState;
label1.Text=当前文件名;
progressBar1.Value=args.ProgressPercentage;
};
worker.RunWorkerCompleted+=(s,args)=>
{
progressBar1.值=0;
};
worker.RunWorkerAsync();
}
应用程序冻结,因为您正在主线程中执行文件解析。您可以使用在新线程上执行操作。以下是一些可能有助于您入门的伪代码:
private void button1_Click(object sender, EventArgs e)
{
var worker = new BackgroundWorker();
worker.DoWork += (s, args) =>
{
// Here you perform the operation and report progress:
int percentProgress = ...
string currentFilename = ...
((BackgroundWorker)s).ReportProgress(percentProgress, currentFilename);
// Remark: Don't modify the GUI here because this runs on a different thread
};
worker.ProgressChanged += (s, args) =>
{
var currentFilename = (string)args.UserState;
// TODO: show the current filename somewhere on the UI and update progress
progressBar1.Value = args.ProgressPercentage;
};
worker.RunWorkerCompleted += (s, args) =>
{
// Remark: This runs when the DoWork method completes or throws an exception
// If args.Error != null report to user that something went wrong
progressBar1.Value = 0;
};
worker.RunWorkerAsync();
}
谢谢关于GUI的评论很好,我得到了一个例外…:)我希望处理文件名而不是percentProgress,为什么不处理百分比?您可以使用
BackgroundWorker.ReportProgress(int,object)
,其中第二个参数是自定义用户状态对象,您可以通过args.UserState
在我的业务类中的ProgressChanged
回调中使用,在循环中,我设置了当前文件的属性。但是我从不传入“ProgressChanged”@Kris,每次调用ReportProgress
方法时都会调用ProgressChanged
回调,因此您需要向业务对象传递一个委托,该委托将指向ReportProgress方法,并且将定期调用该方法。
private void button1_Click(object sender, EventArgs e)
{
var worker = new BackgroundWorker();
worker.DoWork += (s, args) =>
{
// Here you perform the operation and report progress:
int percentProgress = ...
string currentFilename = ...
((BackgroundWorker)s).ReportProgress(percentProgress, currentFilename);
// Remark: Don't modify the GUI here because this runs on a different thread
};
worker.ProgressChanged += (s, args) =>
{
var currentFilename = (string)args.UserState;
// TODO: show the current filename somewhere on the UI and update progress
progressBar1.Value = args.ProgressPercentage;
};
worker.RunWorkerCompleted += (s, args) =>
{
// Remark: This runs when the DoWork method completes or throws an exception
// If args.Error != null report to user that something went wrong
progressBar1.Value = 0;
};
worker.RunWorkerAsync();
}