【问题标题】:C# Webservice: Webmethod, that calls an async method, returns Taskoff objectC# Webservice:Webmethod,调用异步方法,返回Taskoff对象
【发布时间】:2016-07-10 22:00:54
【问题描述】:

我是 web 服务的初学者,我跑进去了 以下问题是关于 web 服务和异步日志记录的。 (c#)

问题描述

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

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

到目前为止,这工作得很好。

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

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

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 后,我注意到网络服务器不再返回“MyClass”-Object,而是“TaskOffCustomClass”-Object。我还没有找到从“TaskOffMyClass”-Object 中获取“MyClass”-Object 的解决方案。

问题

  1. 如何从“TaskOffMyClass”获取“MyClass”对象?

  2. 是否有可能进行异步记录并仍然返回“MyClass”-Object? (使用任务时)

  3. 我考虑过在线程中进行日志记录,但我也读到recommended 在线程上使用任务。切换到 Thread 的影响会有多严重?

【问题讨论】:

  • asyncawait 并不像您认为的那样工作。您在上面的代码中所做的只是使其中的一些在不同的线程上运行,然后 wait 等待该线程在原始线程继续之前完成运行。我强烈建议您花更多时间了解asyncawait。 Eric Lippert 的博客中有大量文章对此进行了解释。
  • 嗨@Damien_The_Unbliever,谢谢您的评论。我一定会看看 Eric Lipperts 的博客。

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


【解决方案1】:

我是网络服务的初学者

我建议您学习一个现代框架。我什至不知道 ASMX 有多老了,现在……根据我能找到的,它“未死”,但我认为这与 Silverlight 是同一种“未死”。换句话说,它已经死了,但他们不想正式说它已经死了。

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

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

首先要意识到 - 如Crowcoder pointed out - 是您可能不想进行即发即弃。如果它工作得很好,那么就保持这样:

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

如果您认识到并接受不受保护的后台操作的缺点(具体而言,它们可以被中止而您无法检测到,这意味着您的日志可能会丢失一些消息),那么您可以使用类似 @987654325 @:

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

我的博客上有alternative approaches 的描述。

【讨论】:

  • 嗨,斯蒂芬,感谢您的支持。我读了@Crowcoder 提到的你的文章,它把我推向了正确的方向。不幸的是,我无法切换到 ASP WebAPI 或 WCF,因为它是现有的 Web 服务。由于我们的团队可以很好地丢失一些日志数据,因此我继续使用 HostingEnvironment。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    你可以使用

    MyClass result = await service.getData();
    

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

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

    【讨论】:

      猜你喜欢
      • 2017-02-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-28
      • 2019-06-10
      • 2020-08-14
      • 1970-01-01
      相关资源
      最近更新 更多