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

时间:2016-03-23 14:35:40

标签: c# web-services asynchronous async-await

我是网络服务的初学者,我跑了进来 以下问题,涉及Web服务和异步日志记录。 (C#)

问题说明

我有一个Web服务,它将一些数据返回给客户端(asp.net网站)。

[WebMethod]
public MyClass getData()
{
    //Do some work
    return _myClassObject;
}

到目前为止这项工作非常好。

因为我想知道webservice发布后发生了什么,我试图实现一些简单的日志记录。

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

public static class Logwriter
{
   public static void writeToLog(string txt)
   {
       //writes log to db
   }
}

我希望这种情况发生异步,因此它不会减慢网络服务的速度。

因此我更改了WebMethod:

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

在我的asp.net网站上更新了ServiceReference之后,我注意到网络服务器不再返回一个&#34; MyClass&#34; -Object,而是一个&#34; TaskOffCustomClass&#34; -Object。我还没有找到从&#34; TaskOffMyClass&#34; -Object获取&#34; MyClass&#34; -Object的解决方案。

问题

  1. 如何获得我的&#34; MyClass&#34;对象来自&#34; TaskOffMyClass&#34;?

  2. 是否有可能异步进行日志记录并仍然返回&#34; MyClass&#34; -Object? (使用任务时)

  3. 我考虑过在线程中进行日志记录,但我也读到使用Task over Thread是recommended。切换到Thread会产生多大的影响?

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

  

我是webservices的初学者

我建议你学习一个现代的框架。我甚至不知道ASMX有多大,现在......根据我能找到的,它已经没有死了#34;但我觉得它是同一种&#34;没死了&#34; Silverlight是。换句话说,它已经死了,但他们并不想正式说它已经死了。

特别是,我不认为ASMX完全理解async或任务。我强烈建议学习ASP.NET WebAPI(如果真的想要SOAP,则推荐WCF)。

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

要实现的第一件事 - 如Crowcoder pointed out - 就是你可能不想做一次即发即弃。如果它运作良好,那就保持这样:

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

如果您认识并接受不受保护的后台操作的缺点(具体而言,它们可以在没有任何方法中止的情况下被中止,这意味着您的日志可能会丢失某些消息),那么您可以使用类似{{{ 1}}:

HostingEnvironment.QueueBackgroundWorkItem

我的博客上有alternative approaches的说明。

答案 2 :(得分:0)

您可以使用

MyClass result = await service.getData();

Task<MyClass> task = service.getData();
MyClass result = task.Result;

在第一个版本中,您的方法立即返回给调用者,并在await完成后getData语句后恢复。
在第二个版本中,对task.Result的调用会阻止执行,直到Task完成。