【问题标题】:can a method with return type as list be called from a thread可以从线程调用返回类型为列表的方法吗
【发布时间】:2013-05-01 13:26:40
【问题描述】:

我有一个调用服务的方法,如下所示。

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

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

【问题讨论】:

  • 他问是否,以及如何在给定返回类型的情况下将该方法作为线程运行。
  • 应该把结果放在哪里?如果你使用 C# 5,你应该看看Async & Await
  • 为什么要在线程中运行它?您希望从中获得什么?我问的原因是你有这个帖子标记为ASP.NET,它可以提供解决这个问题的不同方法。如果您在线程上关闭它,然后无论如何都必须等待结果,您将不会获得任何性能,因为 http 请求仍然需要相同的时间。如果您快速返回基本页面,然后使用 AJAX 作为单独的请求获取此数据,它可能会为您提供更好的性能。因此来自@Silvermind 的问题是什么?
  • 我正在使用 .net4.0 框架。结果列表将用作我的 gridview 的数据源。该服务检查 70 台服务器上的用户是否存在(每台服务器平均有 6 个数据库)并获取用户详细信息(如果存在)。所以处理时间太长了。考虑应用线程,以便进程运行得更快。
  • @Shane.C 如您所见,提供的答案都是假设。它已经在一个线程中运行(我认为他的意思是另一个线程,但我不能假设一切)。这个问题的目的和目的是什么?提问者想要达到什么目的?那是我真正的意思,也许我应该把它打出来,这可能是我的错。

标签: c# asp.net multithreading


【解决方案1】:

在 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/async 关键字,这是上面的一些糖

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

var myResult = await GetAccessListOfMirror(mirrorId, server)

【讨论】:

    【解决方案2】:

    试试这样的:

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

    【讨论】:

      【解决方案3】:

      下面是我使用的一个辅助类,它引用了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);
                          }
                      }
                  });
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-19
        • 2016-06-06
        • 1970-01-01
        • 2015-06-13
        • 2015-05-06
        • 1970-01-01
        • 2014-10-16
        相关资源
        最近更新 更多