Just out of personal interest, I decided to try to write a basic web server using Reactive Extensions (aka Rx). Almost immediately, I came up against the following problem:
HttpListener's async pattern doesn't match the normal async pattern signature, the EndGetContext returns a HttpListenerContext instead of an IAsyncResult!
So my question is: is there a way around this?
Here's some code - the compiler (r开发者_C百科ightly) complains about the second argument to Observable.FromAsyncPattern:
Update - As Jon rightly pointed out, it wasn't the pattern, it's complaining that I haven't provided the return type - this works:
var observable = Observable.FromAsyncPattern<HttpListenerContext>(listener.BeginGetContext, listener.EndGetContext);
The original code:
using System;
using System.Net;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RxWebTest
{
class Program
{
static void Main(string[] args)
{
HttpListener listener = new HttpListener();
try
{
listener.Start();
var observable = Observable.FromAsyncPattern(listener.BeginGetContext, listener.EndGetContext);
Console.ReadLine();
}
finally
{
listener.Abort();
}
}
}
}
That is the normal pattern. It's BeginGetContext
which returns IAsyncResult
; EndGetContext
takes an IAsyncResult
and returns the result of the asynchronous operation - the context. That's exactly the same as (say) Stream.BeginRead
/EndRead
, where EndRead
returns an int
, the number of bytes read.
What happens when you try the code you've posted? I can't immediately see why it wouldn't work.
The trick to figuring out the template parameters for FromAsyncPattern, is to imagine you're creating a Func that is matching the synchronous version of the function.
In this case, the prototype is:
public HttpListenerContext GetContext()
Which means, my Func would look like:
Func<HttpListenerContext>
Then, just take your template parameter and copy-paste it to the FromAsyncPattern.
精彩评论