C# 异步等待web api文件io

C# 异步等待web api文件io,c#,asp.net-web-api,asp.net-4.5,C#,Asp.net Web Api,Asp.net 4.5,我在WebAPI控制器中使用以下异步代码来处理XML文件。一切都按预期进行,但是这是异步/等待方法的正确使用。我基本上是从XML文件中提取所有图像,然后将它们保存到磁盘。我想尝试一种最小化文件io影响的方法 public async Task<HttpResponseMessage> PostFile() { await Task.WhenAll(this.ProcessProofOfPressenceImages(address, images, surveyReferen

我在WebAPI控制器中使用以下异步代码来处理XML文件。一切都按预期进行,但是这是异步/等待方法的正确使用。我基本上是从XML文件中提取所有图像,然后将它们保存到磁盘。我想尝试一种最小化文件io影响的方法

public async Task<HttpResponseMessage> PostFile()
{
    await Task.WhenAll(this.ProcessProofOfPressenceImages(address, images, surveyReference), this.ProcessSketchImages(propertyPlans, images, surveyReference), this.ProcessExteriorImages(exteriorSketch, images, surveyReference));
    //db code
}

private async Task ProcessProofOfPressenceImages(Dictionary<object, object> container, List<Dictionary<string, string>> images, string surveyReference)
{
    if(images != null)
    {
        await Task.WhenAll(this.ProcessImagesHelper(container, images, surveyReference, "propertyImage"));
    }
}

private async Task ProcessSketchImages(Dictionary<object, object> container, List<Dictionary<string, string>> images, string surveyReference)
{
    if(images != null)
    {
        await Task.WhenAll(this.ProcessImagesHelper(container, images, surveyReference, "sketchPlanImage"), this.ProcessImagesHelper(container, images, surveyReference, "sketchFrontImage"), this.ProcessImagesHelper(container, images, surveyReference, "sketchRearImage"), this.ProcessImagesHelper(container, images, surveyReference, "sketchLeftSideImage"), this.ProcessImagesHelper(container, images, surveyReference, "sketchRightSideImage"));
    }
}

private async Task ProcessExteriorImages(Dictionary<object, object> container, List<Dictionary<string, string>> images, string surveyReference)
{
    List<Task> tasks = new List<Task>();

    if(images != null)
    {
        await Task.WhenAll(this.ProcessImagesHelper(container, images, surveyReference, "image1"), this.ProcessImagesHelper(container, images, surveyReference, "image2"), this.ProcessImagesHelper(container, images, surveyReference, "image3"), this.ProcessImagesHelper(container, images, surveyReference, "image4"), this.ProcessImagesHelper(container, images, surveyReference, "image5"), this.ProcessImagesHelper(container, images, surveyReference, "image6"));
    }
}

private async Task ProcessImagesHelper(Dictionary<object, object> container, List<Dictionary<string, string>> images, string surveyReference, string image)
{
    if(container.ContainsKey(image) && !String.IsNullOrEmpty(container[image].ToString()))
    {
        using(MemoryStream memoryStream = new MemoryStream((byte[])container[image]))
        {
            string url = String.Format(@"{0}{1}{2}_{3}.jpg", EcoConfiguration.Instance.RootUrl, EcoConfiguration.Instance.SurveyImageRootUrl, surveyReference, image.SplitOnCapital("_"));

            using(FileStream fileStream = new FileStream(url, FileMode.Create, FileAccess.Write))
            {
                Dictionary<string, string> imageDetails = new Dictionary<string, string>();
                imageDetails.Add("TypeId", ((int)SurveyImageType.Exterior).ToString());
                imageDetails.Add("ImageUrl", url);
                if(container.ContainsKey(image + "Description"))
                {
                    imageDetails.Add("Description", container[image + "Description"].ToSafeString());
                }
                images.Add(imageDetails);
                await memoryStream.CopyToAsync(fileStream);
            }
        }
    }
}
public异步任务PostFile()
{
等待任务.whalll(this.processproof基本图像(地址、图像、surveyReference)、this.ProcessSketchImages(propertyPlans、图像、surveyReference)、this.ProcessExteriorImages(exteriorSketch、图像、surveyReference));
//数据库代码
}
私有异步任务进程Proof PrinceImage(字典容器、列表图像、字符串调查引用)
{
如果(图像!=null)
{
wait Task.WhenAll(this.ProcessImagesHelper(容器、图像、调查参考,“propertyImage”);
}
}
专用异步任务进程SketchImages(字典容器、列表图像、字符串调查引用)
{
如果(图像!=null)
{
等待任务.whalll(this.ProcessImagesHelper(容器,图像,surveyReference,“sketchPlanImage”)、this.ProcessImagesHelper(容器,图像,surveyReference,“sketchFrontImage”)、this.ProcessImagesHelper(容器,图像,surveyReference,“sketchLeftSideImage”)、this.ProcessImagesHelper(容器,图像,surveyReference,“sketchLeftSideImage”),this.ProcessImagesHelper(容器、图像、surveyReference,“sketchRightSideImage”);
}
}
专用异步任务进程外部映像(字典容器、列表映像、字符串调查引用)
{
列表任务=新列表();
如果(图像!=null)
{
等待Task.whalll(this.ProcessImagesHelper(容器,图像,surveyReference,“图像1”)、this.ProcessImagesHelper(容器,图像,surveyReference,“图像2”)、this.ProcessImagesHelper(容器,图像,surveyReference,“图像3”)、this.ProcessImagesHelper(容器,图像,surveyReference,“图像4”)、this.ProcessImagesHelper(container,images,surveyReference,“image5”),这个.ProcessImagesHelper(container,images,surveyReference,“image6”);
}
}
专用异步任务ProcessImagesHelper(字典容器、列表图像、字符串调查参考、字符串图像)
{
if(container.ContainsKey(image)和&!String.IsNullOrEmpty(container[image].ToString())
{
使用(MemoryStream MemoryStream=新的MemoryStream((字节[])容器[image]))
{
字符串url=string.Format(@“{0}{1}{2}{3}.jpg”,EcoConfiguration.Instance.RootUrl,EcoConfiguration.Instance.SurveyImageRootUrl,surveyReference,image.SplitOnCapital(“”);
使用(FileStream FileStream=newfilestream(url、FileMode.Create、FileAccess.Write))
{
Dictionary imageDetails=新建字典();
添加(“TypeId”,((int)SurveyImageType.external.ToString());
添加(“ImageUrl”,url);
if(container.ContainsKey(图像+“说明”))
{
imageDetails.Add(“Description”,容器[image+“Description”].ToSafeString());
}
添加(imageDetails);
等待memoryStream.CopyToAsync(文件流);
}
}
}
}

任何评论/建议都是非常受欢迎的。

关于文件流的棘手问题是,您需要将
isAsync:true
FileOptions.Asynchronous
传递给构造函数/工厂方法以获得真正的异步流。如果不这样做,则底层文件流实际上是阻塞的,而异步us方法只是使用线程池来伪造异步操作

我在代码中看到的另一件事是,您不必要地使用了
async
async
仅在您需要时使用。例如,此方法:

private async Task ProcessProofOfPressenceImages(Dictionary<object, object> container, List<Dictionary<string, string>> images, string surveyReference)
{
  if(images != null)
  {
    await Task.WhenAll(this.ProcessImagesHelper(container, images, surveyReference, "propertyImage"));
  }
}
private async Task processproof基本映像(字典容器、列表映像、字符串调查引用)
{
如果(图像!=null)
{
wait Task.WhenAll(this.ProcessImagesHelper(容器、图像、调查参考,“propertyImage”);
}
}
可以写成:

private Task ProcessProofOfPressenceImages(Dictionary<object, object> container, List<Dictionary<string, string>> images, string surveyReference)
{
  if(images != null)
  {
    return Task.WhenAll(this.ProcessImagesHelper(container, images, surveyReference, "propertyImage"));
  }

  return Task.FromResult<object>(null);
}
private Task processproof基本图像(字典容器、列表图像、字符串调查参考)
{
如果(图像!=null)
{
返回Task.WhenAll(this.ProcessImagesHelper(容器、图像、surveyReference,“propertyImage”);
}
返回Task.FromResult(空);
}
这为您节省了一个不必要的状态机。同样的建议也适用于
ProcessSketchImages
processexterioriorimages

关于
ProcessImagesHelper
,它看起来相当不错,尽管我不确定您为什么需要
MemoryStream
。将字节数组异步写入磁盘也同样容易


如果您对
async
性能提示感兴趣,.

有关文件流的棘手问题是,您需要将
isAsync:true
FileOptions.Asynchronous
传递给构造函数/工厂方法,以获得真正的异步流。如果您不这样做,则底层文件流实际上是阻塞的异步方法只是使用线程池来伪造异步操作

我在代码中看到的另一件事是,您不必要地使用了
async
async
仅在您需要时使用。例如,此方法:

private async Task ProcessProofOfPressenceImages(Dictionary<object, object> container, List<Dictionary<string, string>> images, string surveyReference)
{
  if(images != null)
  {
    await Task.WhenAll(this.ProcessImagesHelper(container, images, surveyReference, "propertyImage"));
  }
}
private async Task processproof基本映像(字典容器、列表映像、字符串调查引用)
{
如果(图像!=null)
{
wait Task.WhenAll(this.ProcessImagesHelper(容器、图像、调查参考,“propertyImage”);
}
}
可以写成:

private Task ProcessProofOfPressenceImages(Dictionary<object, object> container, List<Dictionary<string, string>> images, string surveyReference)
{
  if(images != null)
  {
    return Task.WhenAll(this.ProcessImagesHelper(container, images, surveyReference, "propertyImage"));
  }

  return Task.FromResult<object>(null);
}
private Task processproof基本图像(字典容器、列表图像、字符串调查参考)
{
如果(图像!=null)
{
返回Task.WhenAll(this.ProcessImagesHelper(容器、图像、surveyReference,“propertyImage”);
}
返回Task.FromResult(空);
}