Poniżej znajduje się klasa pomocnika go używać, referencje RX.NET.
Jeśli to, że w projekcie, można wkręcić rzeczy bardzo prosto - kod powyżej was mógłby wydzielić do osobnego wątku, co następuje:
int mirrorId = 0;
string server = "xxx";
ASync.Run<List<AccessDetails>>(GetAccessListOfMirror(mirrorId,server), resultList => {
foreach(var accessDetail in resultList)
{
// do stuff with result
}
}, error => { // if error occured on other thread, handle exception here });
Warto zauważyć: że wyrażenie lambda wróciłem do pierwotnego wątku wywołującego - co jest bardzo przydatne, jeśli np. inicjujesz operacje asynchroniczne z wątku GUI.
Posiada również inną bardzo przydatną metodę: Widelec pozwala odłączyć wiele wątków roboczych i powoduje, że wątek wywołujący blokuje się, aż wszystkie pod-wątki zostaną zakończone lub skasowane.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Concurrency;
namespace MyProject
{
public static class ASync
{
public static void ThrowAway(Action todo)
{
ThrowAway(todo, null);
}
public static void ThrowAway(Action todo, Action<Exception> onException)
{
if (todo == null)
return;
Run<bool>(() =>
{
todo();
return true;
}, null, onException);
}
public static bool Fork(Action<Exception> onError, params Action[] toDo)
{
bool errors = false;
var fork = Observable.ForkJoin(toDo.Select(t => Observable.Start(t).Materialize()));
foreach (var x in fork.First())
if (x.Kind == NotificationKind.OnError)
{
if(onError != null)
onError(x.Exception);
errors = true;
}
return !errors;
}
public static bool Fork<T>(Action<Exception> onError, IEnumerable<T> args, Action<T> perArg)
{
bool errors = false;
var fork = Observable.ForkJoin(args.Select(arg => Observable.Start(() => { perArg(arg); }).Materialize()));
foreach (var x in fork.First())
if (x.Kind == NotificationKind.OnError)
{
if (onError != null)
onError(x.Exception);
errors = true;
}
return !errors;
}
public static void Run<TResult>(Func<TResult> todo, Action<TResult> continuation, Action<Exception> onException)
{
bool errored = false;
IDisposable subscription = null;
var toCall = Observable.ToAsync<TResult>(todo);
var observable =
Observable.CreateWithDisposable<TResult>(o => toCall().Subscribe(o)).ObserveOn(Scheduler.Dispatcher).Catch(
(Exception err) =>
{
errored = true;
if (onException != null)
onException(err);
return Observable.Never<TResult>();
}).Finally(
() =>
{
if (subscription != null)
subscription.Dispose();
});
subscription = observable.Subscribe((TResult result) =>
{
if (!errored && continuation != null)
{
try
{
continuation(result);
}
catch (Exception e)
{
if (onException != null)
onException(e);
}
}
});
}
}
}
Na czym polega problem? – Silvermind
Zapytał, czy, a następnie w jaki sposób można uruchomić tę metodę jako wątek, biorąc pod uwagę jego typ zwracany. –
Gdzie powinien umieścić wynik? Jeśli używasz C# 5, powinieneś spojrzeć na [Async & Await] (http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx) –