C# 可以从线程调用返回类型为list的方法吗

C# 可以从线程调用返回类型为list的方法吗,c#,asp.net,multithreading,C#,Asp.net,Multithreading,我有一个方法,如下所示,它调用一个服务 如何通过线程运行此方法 public List<AccessDetails> GetAccessListOfMirror(string mirrorId,string server) { List<AccessDetails> accessOfMirror = new List<AccessDetails>(); string loginUserId = SessionManager.Session.Cu

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

如何通过线程运行此方法

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;
}
public List GetAccessListOfMirror(字符串镜像ID,字符串服务器)
{
List accessOfMirror=新列表();
字符串loginUserId=SessionManager.Session.Current.LoggedInUserName;
字符串userPassword=SessionManager.Session.Current.Password;
使用(Service1Client client=newservice1client())
{
client.Open();
accessOfMirror=client.GetMirrorList1(mirrorId,server,null);
}
返回对镜像的访问;
}
在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;
}
var task=task.Factory.StartNew(()=>GetAccessListOfMirror(mirrorId,服务器))
.ContinueWith(tsk=>ProcessResult(tsk));
私有void ProcessResult(任务)
{
var result=task.result;
}
在C#4.5中有wait/async关键字,这是上面提到的一些糖分

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

var myResult = await GetAccessListOfMirror(mirrorId, server)
公共异步任务GetAccessListOfMirror(字符串镜像ID,字符串服务器)
var myResult=await GetAccessListOfMirror(mirrorId,服务器)

尝试以下方法:

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;
    }
公共异步任务GetAccessListOfMirror(字符串镜像ID,字符串服务器)
{
List accessOfMirror=新列表();
字符串loginUserId=SessionManager.Session.Current.LoggedInUserName;
字符串userPassword=SessionManager.Session.Current.Password;
使用(Service1Client client=newservice1client())
{
client.Open();
任务详细信息=client.GetMirrorList1(mirrorId,server,null);
accessOfMirror=等待详细信息;
}
返回对镜像的访问;
}

下面是我使用的助手类,它引用了

如果您将其包含在项目中,那么您可以非常简单地执行线程—上面的代码可以拆分为单独的线程,如下所示:

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  });
int-mirrorId=0;
字符串server=“xxx”;
Run(GetAccessListOfMirror(mirrorId,服务器),resultList=>{
foreach(结果列表中的var accessDetail)
{
//用结果做事
}
},error=>{//如果在其他线程上发生错误,请在此处处理异常});
值得注意: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);
                    }
                }
            });
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用系统线程;
使用系统并发;
名称空间MyProject
{
公共静态类异步
{
公共静态无效一次性(操作待办事项)
{
一次性(todo,空);
}
公共静态无效一次性(操作todo、操作onException)
{
如果(todo==null)
返回;
运行(()=>
{
todo();
返回true;
},null,onException);
}
公共静态布尔分叉(操作onError,参数操作[]toDo)
{
布尔误差=假;
var fork=Observable.ForkJoin(toDo.Select(t=>Observable.Start(t.Materialize());
foreach(fork.First()中的变量x)
if(x.Kind==NotificationKind.OnError)
{
如果(onError!=null)
onError(x.例外);
错误=正确;
}
返回!错误;
}
公共静态布尔分叉(Action onError、IEnumerable args、Action perArg)
{
布尔误差=假;
var fork=Observable.ForkJoin(args.Select(arg=>Observable.Start(()=>{perArg(arg);}).Materialize());
foreach(fork.First()中的变量x)
if(x.Kind==NotificationKind.OnError)
{
如果(onError!=null)
onError(x.例外);
错误=正确;
}
返回!错误;
}
公共静态无效运行(Func todo、操作继续、操作OneException)
{
布尔误差=假;
IDisposable订阅=null;
var toCall=可观测的ToAsync(todo);
可观测var=
Observable.CreateWithDisposable(o=>toCall().Subscribe(o)).ObserveOn(Scheduler.Dispatcher).Catch(
(异常错误)=>
{
错误=正确;
if(onException!=null)
一个例外(err);
返回可观察。从不();
}).最后(
() =>
{
if(订阅!=null)
subscription.Dispose();
});
订阅=可观察。订阅((TResult结果)=>
{
如果(!errored&&continuation!=null)
{
尝试
{
继续(结果);
}
捕获(例外e)
{
if(onException!=null)
一个例外(e);
}
}
});
}
}
}

他问,如果给定返回类型,那么该方法是否可以作为线程运行,以及如何作为线程运行。结果应该放在哪里?如果您使用的是C#5,那么您应该看看为什么要在线程中运行它?你希望从中得到什么?我询问的原因是,您将此帖子标记为
ASP.NET
,它可以提供解决此问题的不同方法。如果您在线程上对此进行剥离,然后无论如何都必须等待结果,那么您将无法获得任何性能,因为http请求仍然需要相同的时间。