C# 如何用任务包装EAP模式方法和i进程

C# 如何用任务包装EAP模式方法和i进程,c#,asynchronous,async-await,task,iprogress,C#,Asynchronous,Async Await,Task,Iprogress,我正在使用我自己的“旧”库中的一组synchron函数。这些用于备份文件、压缩文件和上载每个示例。为了进一步使用,我想将这些函数更改为异步函数。请原谅我下面的长篇介绍,但这个问题需要一点背景知识 我发现了一些关于如何转换的信息: 一本好书:斯蒂芬·克利里的《C#Cookbook中的并发性》 下面是我正在学习的模式示例: 这里还有一些帖子: 要点: 使用Async/Await完成所有操作 不要在Asycron模式中使用result或wait包装同步方法。尽可能使用wait 将EA

我正在使用我自己的“旧”库中的一组synchron函数。这些用于备份文件、压缩文件和上载每个示例。为了进一步使用,我想将这些函数更改为异步函数。请原谅我下面的长篇介绍,但这个问题需要一点背景知识

我发现了一些关于如何转换的信息:

一本好书:斯蒂芬·克利里的《C#Cookbook中的并发性》

下面是我正在学习的模式示例:

这里还有一些帖子:

要点:

  • 使用Async/Await完成所有操作
  • 不要在Asycron模式中使用result或wait包装同步方法。尽可能使用wait
  • 将EAP模式方法包装到任务
  • 避免使用任务。在库中运行
  • 在库中使用ConfigureAwait(False)
  • 使用任务。在UI中运行
  • 使用IProgress发布进度
我的基础课看起来是这样的:

public class CompressItem
{
    public string ArchiveName { get; set; }
    public string Status { get; set; }
    public string StatusDetails { get; set; }
    public string SourcePath{ get; set; }
    public string ErrorText { get; set; }
    public int Percent { get; set; }
    public bool IsFinished { get; set; }
    public bool IsCancelling { get; set; }
    public MyClass()
    {
      FileName = Status = SourcePath = StatusDetails = ErrorText = "";
      Precent = 0;
      IsFinished = false;
      IsCancelling = false;
    }
}
    public async Task<bool> CompressDirectoryTaskAsync(CompressItem actionItem,
       IProgress<CompressItem> progress, CancellationToken cancellationToken)
public static Task TestCompressDirectoryTaskAsync(SevenZipCompressor compressor, 
    CompressItem actionItem, IProgress<CompressItem> progress, 
    CancellationToken cancellationToken)
     {  
          // little setup:
          // set 7z.dll path x64/x86
           string path = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), Environment.Is64BitProcess ? "x64" : "x86", "7z.dll");
           SevenZipBase.SetLibraryPath(path);
           // for testing use this
           //SevenZipCompressor compressor = new SevenZipCompressor();
           // specifiy 7z format
           compressor.ArchiveFormat = OutArchiveFormat.SevenZip;
           // use lzma2
           compressor.CompressionMethod = CompressionMethod.Lzma2;
           compressor.CompressionMode = CompressionMode.Create;
           compressor.TempFolderPath = System.IO.Path.GetTempPath();                         
           var tcs = new TaskCompletionSource<EventArgs>();
            // Registering a lambda into the cancellationToken
            cancellationToken.Register(() =>
            {
                // We received a cancellation message, cancel the TaskCompletionSource.Task
                tcs.TrySetCanceled();
            });
            EventHandler<EventArgs> handler = null;               
            try
            { 
                var task = Task.Run(() =>
                {
                    compressor.CompressionFinished += handler = (sender, args) => { tcs.TrySetResult(args); };
                    compressor.Compressing += (sender, args) =>
                    {
                        try
                        {
                            //Check if cancellation has been requested
                            if (cancellationToken != null)
                            {
                                if (cancellationToken.IsCancellationRequested)
                                {
                                    tcs.TrySetCanceled();
                                    //throw new Exception("Cancel Requested");
                                    cancellationToken.ThrowIfCancellationRequested();
                                    //tcs.TrySetException(new Exception("Cancel Requested"));
                                }
                            }

                            //Report progress
                            if (progress != null)
                            {
                                actionItem.IsFinished = false;
                                actionItem.Status = "Compressing in Progess .."
                                actionItem.Percent = args.PercentDone;
                                progress.Report(actionItem);
                            }
                        }
                        catch (Exception e)
                        {
                            tcs.TrySetException(e);
                        }
                    };
                    compressor.BeginCompressDirectory(actionItem.SourcePath, actionItem.ArchiveName);
                    return tcs.Task;
                },cancellationToken);

                return task;
            }
                catch (Exception e)
            {
                compressor.CompressionFinished -= handler;
                tcs.TrySetException(e);
                tcs.TrySetCanceled();
                throw;
            }
        }
(对于进度,我现在使用IProgress,因此我删除了这个类中的旧行)

该类用于库的大多数高级函数,应跟踪所有不同的操作,例如使用SevenZipSharp压缩目录:

public bool CompressDirectory(CompressItem actionItem) 
{
    // Do some stuff with MyClass to get sourcePath and archiveFileName
    //
    ...
    SevenZipCompressor compressor = new SevenZipCompressor();

    // Add Event Handler
    compressor.Compressing += new EventHandler<ProgressEventArgs>((sender, args) =>
                    { CompressItem_ProgressChanged(sender, args, actionItem); });
    compressor.CompressionFinished += new EventHandler<EventArgs>((sender, args) =>
                    { CompressItem_FileCompleted(sender, args, actionItem); });
    compressor.FileCompressionStarted += new EventHandler<FileNameEventArgs>((sender, args) =>
                    { CompressItem_FileCompressionStarted(sender, args, actionItem); });
    // Start Compression
    compressor.CompressDirectory(sourcePath, archiveFileName);
   ...
   ...
}
public bool CompressDirectory(CompressItem actionItem)
{
//使用MyClass执行一些操作以获取sourcePath和archiveFileName
//
...
SevenZipCompressor压缩机=新的SevenZipCompressor();
//添加事件处理程序
compressor.Compressing+=新事件处理程序((发送方,参数)=>
{CompressItem_ProgressChanged(发送方、参数、操作项);});
compressor.CompressionFinished+=新事件处理程序((发送方,参数)=>
{CompressItem_FileCompleted(发送方、参数、操作项);});
compressor.FileCompressionStarted+=新事件处理程序((发送方,参数)=>
{CompressItem_FileCompressionStarted(发送方、args、actionItem);});
//开始压缩
compressor.CompressDirectory(sourcePath,archiveFileName);
...
...
}
如您所见,我使用eventhandler还发送类的对象,以便能够在进度旁边捕获其他信息,如操作、状态或状态详细信息。 那么现在我的问题是:

对于基于异步任务的方法,应将其转换为如下模式:

public class CompressItem
{
    public string ArchiveName { get; set; }
    public string Status { get; set; }
    public string StatusDetails { get; set; }
    public string SourcePath{ get; set; }
    public string ErrorText { get; set; }
    public int Percent { get; set; }
    public bool IsFinished { get; set; }
    public bool IsCancelling { get; set; }
    public MyClass()
    {
      FileName = Status = SourcePath = StatusDetails = ErrorText = "";
      Precent = 0;
      IsFinished = false;
      IsCancelling = false;
    }
}
    public async Task<bool> CompressDirectoryTaskAsync(CompressItem actionItem,
       IProgress<CompressItem> progress, CancellationToken cancellationToken)
public static Task TestCompressDirectoryTaskAsync(SevenZipCompressor compressor, 
    CompressItem actionItem, IProgress<CompressItem> progress, 
    CancellationToken cancellationToken)
     {  
          // little setup:
          // set 7z.dll path x64/x86
           string path = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), Environment.Is64BitProcess ? "x64" : "x86", "7z.dll");
           SevenZipBase.SetLibraryPath(path);
           // for testing use this
           //SevenZipCompressor compressor = new SevenZipCompressor();
           // specifiy 7z format
           compressor.ArchiveFormat = OutArchiveFormat.SevenZip;
           // use lzma2
           compressor.CompressionMethod = CompressionMethod.Lzma2;
           compressor.CompressionMode = CompressionMode.Create;
           compressor.TempFolderPath = System.IO.Path.GetTempPath();                         
           var tcs = new TaskCompletionSource<EventArgs>();
            // Registering a lambda into the cancellationToken
            cancellationToken.Register(() =>
            {
                // We received a cancellation message, cancel the TaskCompletionSource.Task
                tcs.TrySetCanceled();
            });
            EventHandler<EventArgs> handler = null;               
            try
            { 
                var task = Task.Run(() =>
                {
                    compressor.CompressionFinished += handler = (sender, args) => { tcs.TrySetResult(args); };
                    compressor.Compressing += (sender, args) =>
                    {
                        try
                        {
                            //Check if cancellation has been requested
                            if (cancellationToken != null)
                            {
                                if (cancellationToken.IsCancellationRequested)
                                {
                                    tcs.TrySetCanceled();
                                    //throw new Exception("Cancel Requested");
                                    cancellationToken.ThrowIfCancellationRequested();
                                    //tcs.TrySetException(new Exception("Cancel Requested"));
                                }
                            }

                            //Report progress
                            if (progress != null)
                            {
                                actionItem.IsFinished = false;
                                actionItem.Status = "Compressing in Progess .."
                                actionItem.Percent = args.PercentDone;
                                progress.Report(actionItem);
                            }
                        }
                        catch (Exception e)
                        {
                            tcs.TrySetException(e);
                        }
                    };
                    compressor.BeginCompressDirectory(actionItem.SourcePath, actionItem.ArchiveName);
                    return tcs.Task;
                },cancellationToken);

                return task;
            }
                catch (Exception e)
            {
                compressor.CompressionFinished -= handler;
                tcs.TrySetException(e);
                tcs.TrySetCanceled();
                throw;
            }
        }
公共异步任务CompressDirectoryStaskAsync(CompressItem actionItem,
i进程进度,取消令牌取消令牌)
这意味着我需要将上面的函数包装成这样。 SevenZipSharp中的Eventhandler使用EventArgs,而不是AsyncCompletedEventArgs的后代。 有更好的方法吗

更新2: 我将压缩部分包装到一个任务中,以便能够在需要时取消它。 SevenZipCompressor不支持取消。因此,通常我应该在库中避免使用task.run,但不知道其他方法。 我还更改了BeginCompressDirectoy,因为它在开始压缩之后返回,而不是像CompressDirectory一样阻塞线程,直到完成。到目前为止进展顺利,但没有取消。只需一小步就可以完成左。。。希望你能帮忙

!!要测试此功能,只需安装nuget软件包Squid-Box.SevenZipSharp

到目前为止,我试着像这样包装Sevenzipc压缩机:

public class CompressItem
{
    public string ArchiveName { get; set; }
    public string Status { get; set; }
    public string StatusDetails { get; set; }
    public string SourcePath{ get; set; }
    public string ErrorText { get; set; }
    public int Percent { get; set; }
    public bool IsFinished { get; set; }
    public bool IsCancelling { get; set; }
    public MyClass()
    {
      FileName = Status = SourcePath = StatusDetails = ErrorText = "";
      Precent = 0;
      IsFinished = false;
      IsCancelling = false;
    }
}
    public async Task<bool> CompressDirectoryTaskAsync(CompressItem actionItem,
       IProgress<CompressItem> progress, CancellationToken cancellationToken)
public static Task TestCompressDirectoryTaskAsync(SevenZipCompressor compressor, 
    CompressItem actionItem, IProgress<CompressItem> progress, 
    CancellationToken cancellationToken)
     {  
          // little setup:
          // set 7z.dll path x64/x86
           string path = Path.Combine(Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory), Environment.Is64BitProcess ? "x64" : "x86", "7z.dll");
           SevenZipBase.SetLibraryPath(path);
           // for testing use this
           //SevenZipCompressor compressor = new SevenZipCompressor();
           // specifiy 7z format
           compressor.ArchiveFormat = OutArchiveFormat.SevenZip;
           // use lzma2
           compressor.CompressionMethod = CompressionMethod.Lzma2;
           compressor.CompressionMode = CompressionMode.Create;
           compressor.TempFolderPath = System.IO.Path.GetTempPath();                         
           var tcs = new TaskCompletionSource<EventArgs>();
            // Registering a lambda into the cancellationToken
            cancellationToken.Register(() =>
            {
                // We received a cancellation message, cancel the TaskCompletionSource.Task
                tcs.TrySetCanceled();
            });
            EventHandler<EventArgs> handler = null;               
            try
            { 
                var task = Task.Run(() =>
                {
                    compressor.CompressionFinished += handler = (sender, args) => { tcs.TrySetResult(args); };
                    compressor.Compressing += (sender, args) =>
                    {
                        try
                        {
                            //Check if cancellation has been requested
                            if (cancellationToken != null)
                            {
                                if (cancellationToken.IsCancellationRequested)
                                {
                                    tcs.TrySetCanceled();
                                    //throw new Exception("Cancel Requested");
                                    cancellationToken.ThrowIfCancellationRequested();
                                    //tcs.TrySetException(new Exception("Cancel Requested"));
                                }
                            }

                            //Report progress
                            if (progress != null)
                            {
                                actionItem.IsFinished = false;
                                actionItem.Status = "Compressing in Progess .."
                                actionItem.Percent = args.PercentDone;
                                progress.Report(actionItem);
                            }
                        }
                        catch (Exception e)
                        {
                            tcs.TrySetException(e);
                        }
                    };
                    compressor.BeginCompressDirectory(actionItem.SourcePath, actionItem.ArchiveName);
                    return tcs.Task;
                },cancellationToken);

                return task;
            }
                catch (Exception e)
            {
                compressor.CompressionFinished -= handler;
                tcs.TrySetException(e);
                tcs.TrySetCanceled();
                throw;
            }
        }
公共静态任务TestCompressDirectoryStaskAsync(SevenZipCompressor compressor,
压缩项操作项,i进度,
取消令牌(取消令牌)
{  
//小设置:
//设置7z.dll路径x64/x86
字符串path=path.Combine(path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory),Environment.is64位进程?“x64”:“x86”,“7z.dll”);
SevenZipBase.SetLibraryPath(路径);
//对于测试,请使用此
//SevenZipCompressor压缩机=新的SevenZipCompressor();
//指定7z格式
compressor.ArchiveFormat=OutArchiveFormat.SevenZip;
//使用lzma2
compressor.CompressionMethod=CompressionMethod.Lzma2;
compressor.CompressionMode=CompressionMode.Create;
compressor.TempFolderPath=System.IO.Path.GetTempPath();
var tcs=new TaskCompletionSource();
//将lambda注册到cancellationToken中
cancellationToken.Register(()=>
{
//我们收到一条取消消息,取消TaskCompletionSource.Task
tcs.trysetconceled();
});
EventHandler=null;
尝试
{ 
var task=task.Run(()=>
{
compressor.CompressionFinished+=handler=(发送方,args)=>{tcs.TrySetResult(args);};
压缩程序+=(发送方,参数)=>
{
尝试
{
//检查是否已请求取消
if(cancellationToken!=null)
{
if(cancellationToken.IsCancellationRequested)
{
tcs.trysetconceled();
//抛出新异常(“请求取消”);
cancellationToken.ThrowIfCancellationRequested();
//tcs.TrySetException(新异常(“请求取消”);
}
}
//报告进展
如果(进度!=null)
{
actionItem.IsFinished=false;
行动一