I'm trying to get in to workflow foundation but apparently i can't seem to get even the most basic implementation of an async activity working.
Could anyone point me in the right direction with this activity I have put together in order to make an async OData request using HttpClient ...
Firstly I created a base type extending from AsyncCodeActivity ...
public abstract class ODataActivity<TResult> : AsyncCodeActivity<TResult>, IDisposable
{
protected HttpClient Api =
new HttpClient(
new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate }
)
{ BaseAddress = new Uri(new Config().ApiRoot) };
bool disposed = false;
public void Dispose()
{
Dispose(disposed);
}
public virtual void Dispose(bool disposed)
{
if (!disposed)
{
Api.Dispose();
Api = null;
}
}
}
Next I inherit that to provide my implementation ...
public class ODataFetchActivity<TResult> : ODataActivity<TResult>
{
public string Query { get; set; }
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
var task = Api.GetAsync(Query)
.ContinueWith(t => t.Result.Content.ReadAsAsync<TResult>())
.ContinueWith(t => callback(t));
context.UserState = task;
return task;
}
protected override TResult EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
var response = ((Task<TResult>)result).Result;
context.SetValue(Result, response);
return response;
}
}
... the idea being that this activity can do only get requests, i could then implement a post, put and delete to get full crud in the same manner on top of my base type above.
The problem comes when i add this to a workflow and try to execute the flow using a re-hosted designer in a new wpf app resulting in the following exception ...
Edit:
So I did a little bit more tinkering and have something that appears to not complain but i'm not convinced this is a "good" way to handle this as Task implements IAsyncResult directly and it feels like i'm jumping through a bunch of hoops I perhaps don't need to.
public class ODataFetchActivity<TResult> : ODataActivity<TResult>
{
public string Query { get; set; }
Func<TResult> work;
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
work = () => Api.Get<TResult>(Query).Result;
context.UserState = work;
return work.BeginInvoke(callback, state);
}
protected override TResult EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
TResult response = work.EndInvoke(result);
Result.Set(context, response);
return response;
}
}
This appears to compile and run but i can't help but feel like there's a cleaner way to handle this.
Hmm apparently this works fine ...
public class ODataFetchActivity<TResult> : ODataActivity<TResult>
{
public string Query { get; set; }
Func<TResult> work;
protected override IAsyncResult BeginExecute(AsyncCodeActivityContext context, AsyncCallback callback, object state)
{
work = () => Api.Get<TResult>(Query).Result;
context.UserState = work;
return work.BeginInvoke(callback, state);
}
protected override TResult EndExecute(AsyncCodeActivityContext context, IAsyncResult result)
{
TResult response = work.EndInvoke(result);
Result.Set(context, response);
return response;
}
}
I was getting some odd behavior from the designer re-hosting where it would run the previous version until a save made (no idea why)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With