2016-03-23 5 views
2

Ich bin ein totaler Anfänger mit Webservices und ich lief in das folgende Problem, das über einen Webservice und asynchrone Protokollierung ist. (C#)C# Webservice: Webmethod, das eine async Methode aufruft, gibt das Taskoff Objekt zurück

Problem Beschreibung

Ich habe einen Webservice, der einige Daten an einen Client (asp.net Website) zurückgibt.

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

Das funktioniert bisher ziemlich gut.

Da ich wissen möchte, was auf dem Webservice passiert, sobald es veröffentlicht wird, habe ich versucht, einige einfache Protokollierung zu implementieren.

Die folgende Klasse (vereinfacht) übernimmt die Protokollierung:

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

Ich möchte diese asynchron geschehen, so wird es auf den Webdienst nicht verlangsamen.

Deshalb änderte ich das WebMethod:

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

Nachdem ich das Servicereference auf meiner asp.net Website aktualisiert ich, dass der Webserver nicht mehr bemerkt, eine „MyClass“ -Objekt zurückgibt, sondern eine „TaskOffCustomClass“ -Objekt . Ich habe noch keine Lösung gefunden, um das "MyClass" -Objekt vom "TaskOffMyClass" -Objekt zu bekommen.

Fragen

  1. Wie kann ich meine "MyClass" Objekt von "TaskOffMyClass" erhalten?

  2. Gibt es eine Möglichkeit, die asynchrone Protokollierung durchzuführen und immer noch ein "MyClass" -Objekt zurückgeben? (während Task)

  3. Ich dachte über die Protokollierung in einem Thread, aber ich lese auch, dass es recommended Task over Thread verwenden. Wie schlimm wäre der Wechsel zu Thread?

+2

'async' und' erwarten' funktionieren nicht so, wie Sie zu denken scheinen. Alles, was Sie in Ihrem obigen Code getan haben, ist, dass ein Teil davon in einem anderen Thread ausgeführt wird, aber warten Sie *, bis dieser Thread fertig ist, bevor der ursprüngliche Thread fortgesetzt wird. Ich schlage vor, dass Sie mehr Zeit damit verbringen, etwas über "Async" und "Warten" zu lernen. Eric Lipperts Blog hatte eine gute Anzahl von Artikeln, die es erklärten. –

+0

Hi @Damien_The_Unbliever, danke für deinen Kommentar. Ich werde auf jeden Fall einen Blick auf Eric Lipperts Blog werfen. – Martin

Antwort

0

Ich bin ein totaler Anfänger mit Webdiensten

Ich empfehle Ihnen einen modernen Rahmen lernen. Ich weiß nicht einmal, wie alt ASMX jetzt ist ... Nach dem, was ich finden konnte, ist es "nicht tot", aber ich denke, das ist die gleiche Art von "nicht tot" wie Silverlight. Mit anderen Worten, es ist tot, aber sie wollen nicht offiziell sagen, dass es tot ist.

Insbesondere glaube ich nicht, dass ASMX async oder Aufgaben überhaupt versteht. I stark empfehlen lernen ASP.NET WebAPI (oder WCF, wenn Sie wirklich SOAP wollen).

Wenn Sie jedoch bestehende Web-Methoden, die Sie pflegen müssen, dann ...

Das erste, was zu realisieren - als Crowcoder pointed out - ist, dass Sie wahrscheinlich nicht wollen, zu tun, fire-and-forget . Wenn es gut genug funktioniert, dann nur halten sie wie folgt aus:

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

Wenn Sie die Nachteile der ungeschützten Hintergrundoperationen (spezifisch erkennen und akzeptieren, dass sie ohne irgendeine Weise abgebrochen werden kann, das für Sie zu erkennen, was bedeutet, dass Ihre Log einige Nachrichten fehlen dürfen), dann können Sie so etwas wie HostingEnvironment.QueueBackgroundWorkItem verwenden:

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

ich habe eine Beschreibung von alternative approaches auf meinem Blog.

+0

Hallo Stephen, Tank dich für deine Unterstützung. Ich habe deinen Artikel von @Crowcoder gelesen und es hat mich in die richtige Richtung gedrängt. Leider kann ich nicht zu ASP WebAPI oder WCF wechseln, da es sich um einen bestehenden Webservice handelt. Da es unserem Team gut geht, einige Log-Daten zu verlieren, habe ich mit HostingEnvironment weitergemacht. – Martin

0

Sie könnte entweder

MyClass result = await service.getData(); 

oder

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

In der ersten Version, Ihre Methode kehrt zum Anrufer verwenden sofort und ist nach dem await Anweisung, wenn getData beendet wieder aufgenommen.
In der zweiten Version blockiert der Aufruf an task.Result Ausführung, bis die Task abgeschlossen ist.

2

Sie sind hier sehr durcheinander. Hoffentlich wird Stephen Cleary auch antworten, aber Sie sollten niemals Task.Run() in ASP.Net. Sie würden writeToLog async machen. Bis zur Rückgabe der Aufgabe hat @Rene einige gute Ratschläge, aber verwenden Sie auch nicht .Result in ASP.Net wegen möglicher Deadlocks. Ein Feuer-und-vergessen-Vorgang wie Protokollierung ist überraschend komplex zu do right.. Sie sollten Ihr Protokoll besser zur Verarbeitung an eine Warteschlange senden.

Verwandte Themen