C#Webservice:Webmethod调用异步方法,返回Taskoff对象

C#Webservice:Webmethod调用异步方法,返回Taskoff对象,c#,web-services,asynchronous,async-await,C#,Web Services,Asynchronous,Async Await,我完全是一个网络服务的初学者,我跑了进去 下面的问题与Web服务和异步日志记录有关。(c#) 问题描述 我有一个向客户端(asp.net网站)返回一些数据的Web服务 到目前为止,效果相当不错 因为我想知道Web服务发布后会发生什么,所以我尝试实现一些简单的日志记录 以下类(简化)处理日志记录: public static class Logwriter { public static void writeToLog(string txt) { //writes log

我完全是一个网络服务的初学者,我跑了进去 下面的问题与Web服务和异步日志记录有关。(c#)

问题描述

我有一个向客户端(asp.net网站)返回一些数据的Web服务

到目前为止,效果相当不错

因为我想知道Web服务发布后会发生什么,所以我尝试实现一些简单的日志记录

以下类(简化)处理日志记录:

public static class Logwriter
{
   public static void writeToLog(string txt)
   {
       //writes log to db
   }
}
我希望这是异步的,这样就不会减慢Web服务的速度

因此,我更改了WebMethod:

[WebMethod]
public async Task<MyClass> getData()
{
    await Task.Run(() => Logwriter.writeToLog("Someone requested the WebMethod 'GetData'"));
    //Do some work
    return _myClassObject;
}
[WebMethod]
公共异步任务getData()
{
wait Task.Run(()=>Logwriter.writeToLog(“有人请求了WebMethod'GetData'));
//做些工作
返回_myClassObject;
}
在我更新asp.net网站上的ServiceReference之后,我注意到Web服务器不再返回“MyClass”对象,而是返回“TaskOffCustomClass”对象。我还没有找到从“TaskOffMyClass”对象获取“MyClass”对象的解决方案

问题

  • 如何从“TaskOffMyClass”获取“MyClass”对象

  • 是否有可能进行异步日志记录并仍然返回“MyClass”对象?(使用任务时)

  • 我曾考虑过在线程中进行日志记录,但我也读到它是在线程上使用任务。切换到线程的影响有多大

  • 你可以用

    MyClass result = await service.getData();
    

    Task=service.getData();
    MyClass结果=task.result;
    
    在第一个版本中,您的方法立即返回调用方,并在
    getData
    完成后在
    wait
    语句后恢复
    在第二个版本中,对
    task.Result
    的调用会阻止执行,直到
    任务完成。

    您在这里非常混乱。希望Stephen Cleary也能回答,但您永远不应该在ASP.Net中
    Task.Run()
    。您将使
    writeToLog
    async。 至于返回任务,@Rene有一些很好的建议,但也不要在ASP.Net中使用
    .Result
    ,因为可能会出现死锁。 像日志记录这样的失火遗忘操作对用户来说异常复杂。 您最好将日志发送到队列进行处理

    我对Web服务完全是个初学者

    我建议你学习一个现代的框架。我都不知道阿斯姆克斯有多大了,现在。。。根据我所能找到的,它是“未死的”,但我认为这与Silverlight是同一种“未死的”。换句话说,它死了,但他们不想正式说它死了

    特别是,我认为ASMX根本不理解
    async
    或任务。我强烈建议您学习ASP.NET WebAPI(如果您真的需要SOAP,也可以学习WCF)

    但是,如果您需要维护现有的web方法,那么

    要意识到的第一件事是,你可能不想做一件“火与忘”的事。如果它工作得足够好,就保持这样:

    [WebMethod]
    public MyClass getData()
    {
      Logwriter.writeToLog("Someone requested the WebMethod 'GetData'");
      //Do some work
      return _myClassObject;
    }
    
    如果您认识到并接受未受保护的后台操作的缺点(特别是,它们可以在您无法检测到的情况下中止,这意味着您的日志可能会丢失一些消息),那么您可以使用类似于
    HostingEnvironment.QueueBackgroundWorkItem

    [WebMethod]
    public MyClass getData()
    {
      HostingEnvironment.QueueBackgroundWorkItem(() => Logwriter.writeToLog("Someone requested the WebMethod 'GetData'"));
      //Do some work
      return _myClassObject;
    }
    

    我在我的博客上有对的描述。

    async
    wait
    不像你想象的那样工作。在上面的代码中,您所做的只是使其中一些线程在不同的线程上运行,然后等待该线程完成运行,然后原始线程才能继续。我强烈建议您花更多时间学习
    async
    wait
    。Eric Lippert的博客上有很多文章对此进行了解释。嗨@Damien_The_Unbliever,谢谢你的评论。我一定会看看埃里克·利珀斯的博客。嗨,斯蒂芬,谢谢你的支持。我读了@Crowcoder写的你的文章,它把我推向了正确的方向。不幸的是,我无法切换到ASP WebAPI或WCF,因为它是一个现有的Web服务。由于我们的团队对丢失一些日志数据没有意见,我继续使用HostingEnvironment。
    [WebMethod]
    public MyClass getData()
    {
      Logwriter.writeToLog("Someone requested the WebMethod 'GetData'");
      //Do some work
      return _myClassObject;
    }
    
    [WebMethod]
    public MyClass getData()
    {
      HostingEnvironment.QueueBackgroundWorkItem(() => Logwriter.writeToLog("Someone requested the WebMethod 'GetData'"));
      //Do some work
      return _myClassObject;
    }