客户需求如下:
-
要求系统能够同时导入A、B、C、D四个文件。
-
如果某个文件导入的时候出错,显示错误信息,其它文件能够继续导入。
-
全部导入之后,通知主线程,程序结束。
最终决定采用异步委托解决这个问题。
首先编写一个委托,通过需求可以知道,委托的方法名如下:
///
/// Import Data Delegate
///
/// 导入文件路径
public delegate void ImportDataCallBack(string filePath);
/// Import Data Delegate
///
/// 导入文件路径
public delegate void ImportDataCallBack(string filePath);
编写FileType枚举,用来表示传递的是哪个文件,因为系统只要求录入四中固定的文件,所以采用枚举。
public enum FileType
{
File_A,
File_B,
File_C,
File_D
}
{
File_A,
File_B,
File_C,
File_D
}
为了让每个文件导入之后,都可以通知主程序,我们还需要编写一个统一的回调函数。
private void FinishImport(IAsyncResult result)
{
if (result.IsCompleted)
{
switch ((FileType)result.AsyncState)
{
if (result.IsCompleted)
{
switch ((FileType)result.AsyncState)
{
case FileType.File_A:
case FileType.File_A:
isFinishedFileA = true;
break;
case FileType.File_B:
isFinishedFileB = true;
break;
case FileType.File_C:
isFinishedFileC = true;
break;
case FileType.File_D:
isFinishedFileD = true;
break;
default:
break;
}
if (isFinishedFileA && isFinishedFileB && isFinishedFileC && isFinishedFileD)
{
Environment.Exit(0);
}
}
}
}
为了让每个文件导入的过程中,如果出错,都能得到我们想得到的消息,我们这里自定义一个异常。
public class WorkThreadException : ApplicationException
{
private FileType fileType;
public FileType FileType
{
get { return fileType; }
{
private FileType fileType;
public FileType FileType
{
get { return fileType; }
set { fileType = value; }
}
public WorkThreadException(string message)
: base(message)
{
}
public WorkThreadException()
{ }
public WorkThreadException(FileType fileType, string message)
: base(message)
{
this.fileType = fileType;
}
}
}
public WorkThreadException(string message)
: base(message)
{
}
public WorkThreadException()
{ }
public WorkThreadException(FileType fileType, string message)
: base(message)
{
this.fileType = fileType;
}
}
剩下的就是几个文件的导入函数了,File A的代码如下,
public void ImportFileA(string filepath)
{
try
{
{
try
{
// to do : import file a here
}
catch (Exception ex)
{
WorkThreadException e = new WorkThreadException(ex.Message, FileType.File_A);
catch (Exception ex)
{
WorkThreadException e = new WorkThreadException(ex.Message, FileType.File_A);
throw (e);
}
}
}
其它的类似,就不写了。
当然,如果为了扩展性考虑的话,你可以写一个接口,然后实现该接口。
最后,在客户端delegate的beginInvoke方法调用这几个导入函数就可以了
ImportDataCallBack fileA = new ImportDataCallBack(ImportFileA);
fileA.BeginInvoke("FileA_Path", FinishImport, FileType.File_A);
ImportDataCallBack fileB = new ImportDataCallBack(ImportFileB);
fileA.BeginInvoke("FileB_Path", FinishImport, FileType.File_B);
ImportDataCallBack fileC = new ImportDataCallBack(ImportFileC);
fileA.BeginInvoke("FileC_Path", FinishImport, FileType.File_C);
ImportDataCallBack fileD = new ImportDataCallBack(ImportFileD);
fileA.BeginInvoke("FileD_Path", FinishImport, FileType.File_D);
fileA.BeginInvoke("FileA_Path", FinishImport, FileType.File_A);
ImportDataCallBack fileB = new ImportDataCallBack(ImportFileB);
fileA.BeginInvoke("FileB_Path", FinishImport, FileType.File_B);
ImportDataCallBack fileC = new ImportDataCallBack(ImportFileC);
fileA.BeginInvoke("FileC_Path", FinishImport, FileType.File_C);
ImportDataCallBack fileD = new ImportDataCallBack(ImportFileD);
fileA.BeginInvoke("FileD_Path", FinishImport, FileType.File_D);
总结:感觉异步委托是比线程和线程池等更为轻量级的异步处理方式,简单的调用,方便的回调函数,都可以简化我们的某些异步开发过程。