从Task获取对象并从非异步方法返回

时间:2013-06-05 01:11:45

标签: c# asp.net-web-api async-await class-library

我有一个较低级别的库,我设计的其中一种方法是异步并返回一个任务。

我知道在较低级别的库中使用异步方法并不是一个好主意,但是没有办法解决这个问题,因为处理的起伏程度如何。

在我的低级库之间,我有一个主库,它暴露了有问题的低级库方法。 “就像商业层一样。”

我的应用程序的入口点是WEB Api,然后它调用中级库,而中级调用最低级别的库。

我的相关问题是,从我的mid库中开始异步链的最低级库中解压缩结果,然后向消费者公开一个静态方法,或者我应该只为消费者提供一个异步方法并提供从最低到最高的异步方法?

从进入应用程序开始,第一个方法是:CutSheet.CutSheet cutSheet = AlumCloudPlans.Manager.GetCutSheet(elev);

我知道必须有更好的方法,因为在中级库中我必须创建一个完整的新任务,返回值是一个Task,返回Task值。

我会建议您在中级库中做什么?

---最低级别

namespace CutSheet
{
    public class Manager
    {
        public async static Task<CutSheet> GetCutSheet(IElevation elevation)
        {
            return new CutSheet(await new PartsProcessor.PartProcessor()
                                                 .ProcessParts(elevation));
        }
    }
}

---中级

namespace AlumCloudPlans
{
    public class Manager
    {    
        public static CutSheet.CutSheet GetCutSheet(IElevation elevation)
        {
            var t = Task.Factory.StartNew(async delegate
            {
                return await CutSheet.Manager.GetCutSheet(elevation);
            });

            t.Wait();
            return t.Result.Result;
        }

    }
}

---最高级别和进入应用

namespace StorefrontSystem.Controllers
{
    [Authorize]
    public class CutSheetController : AlumCloudWebApiBaseController
    {

        public async Task<HttpResponseMessage> Get(string a, string f, int id)
        {
            HttpResponseMessage r = Request.CreateResponse();

            IElevation elev = await ElevationManager.GetElevation(id);

            CutSheet.CutSheet cutSheet = AlumCloudPlans.Manager
                                                   .GetCutSheet(elev);

            var ms = new MemoryStream();
            bool isPDF = f.ToLower() == "pdf";

            if (isPDF)
            {
                using (var pdf = await cutSheet.GetCutSheetPDF(elev))
                {
                    pdf.Save(ms, false);
                }
            }
            else
            {    
                using (Bitmap canvas = await cutSheet.GetDrawing())
                {
                    canvas.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                }    
            }

            ms.Position = 0;
            r.Content = new StreamContent(ms);
            if (isPDF)
            {
                r.Content.Headers.ContentType 
                      = new Headers.MediaTypeHeaderValue("Application/pdf");
            }
            else
            {
                r.Content.Headers.ContentType 
                     = new Headers.MediaTypeHeaderValue("image/png");
            }
            return r;
        }
    }
}

1 个答案:

答案 0 :(得分:4)

  

我知道在低级库中使用异步方法不是一个好主意

谁告诉过你的?在任何级别使用async方法是一个非常好的主意,只要您正在进行的操作自然是异步的。但是,通过使用Task.Run 假装某些东西是异步的,是一个好主意 - 在ASP.NET中尤其如此。

假设您的操作自然是异步的,您应该一直使用async

中层:

public class Manager
{
    public static Task<CutSheet.CutSheet> GetCutSheetAsync(IElevation elevation)
    {
        return CutSheet.Manager.GetCutSheetAsync(elevation);
    }
}

最高级别:

[Authorize]
public class CutSheetController : AlumCloudWebApiBaseController
{
    public async Task<HttpResponseMessage> Get(string a, string f, int id)
    {
        HttpResponseMessage r = Request.CreateResponse();

        IElevation elev = await ElevationManager.GetElevationAsync(id);

        CutSheet.CutSheet cutSheet = await AlumCloudPlans.Manager.GetCutSheetAsync(elev);

        ...
   }
}