2013-05-01 73 views
7

我有一个方法,如下所示,它调用一个服务。可以从线程调用返回类型列表的方法

如何通过线程运行此方法?

public List<AccessDetails> GetAccessListOfMirror(string mirrorId,string server) 
{ 
    List<AccessDetails> accessOfMirror = new List<AccessDetails>(); 
    string loginUserId = SessionManager.Session.Current.LoggedInUserName; 
    string userPassword = SessionManager.Session.Current.Password; 

    using (Service1Client client = new Service1Client()) 
    { 
     client.Open(); 
     accessOfMirror = client.GetMirrorList1(mirrorId, server, null); 
    } 

    return accessOfMirror; 
} 
+1

什么问题? – Silvermind 2013-05-01 13:29:20

+0

他问是否,以及如何将该方法作为线程运行,并给出其返回类型。 – 2013-05-01 13:29:57

+1

它应该把结果放在哪里?如果你正在使用C#5,你应该看看[Async&Await](http://msdn.microsoft.com/en-us/library/vstudio/hh191443.aspx) – 2013-05-01 13:30:45

回答

3

在C#3.5或4.0中,您可以执行此操作。

var task = Task.Factory.StartNew<List<AccessDetails>>(() => GetAccessListOfMirror(mirrorId,server)) 
.ContinueWith(tsk => ProcessResult(tsk)); 

private void ProcessResult(Task task) 
{ 
    var result = task.Result; 
} 

在C#4.5还有的的await /异步关键字是一些糖以上

public async Task<List<AccessDetails>> GetAccessListOfMirror(string mirrorId,string server) 

var myResult = await GetAccessListOfMirror(mirrorId, server) 
1

尝试是这样的:

public async Task<List<AccessDetails>> GetAccessListOfMirror(string mirrorId, string server) 
    { 
     List<AccessDetails> accessOfMirror = new List<AccessDetails>(); 
     string loginUserId = SessionManager.Session.Current.LoggedInUserName; 
     string userPassword = SessionManager.Session.Current.Password; 


     using (Service1Client client = new Service1Client()) 
     { 
      client.Open(); 
      Task<List<AccessDetails>> Detail = client.GetMirrorList1(mirrorId, server, null); 
      accessOfMirror = await Detail; 

     } 


     return accessOfMirror; 
    } 
0

下面是一个辅助类我使用,它参考文献RX.NET

如果包含在你的项目,那么你可以线程的东西很简单 - 你上面的代码如下所示可以分拆到一个单独的线程:

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 }); 

值得注意:即lambda表达式是合并回原来的调用线程 - 例如,如果您从GUI线程启动异步操作,这非常方便。

它还有另一个非常方便的方法:Fork允许您分离多个工作线程并导致调用线程阻塞,直到所有子线程完成或出错。

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); 
        } 
       } 
      }); 
     } 
    } 
}