1

我有一个 UI,它调用一个名为“LongRunningProcess”的 WCF 方法——WCF 已经为我生成了异步方法“BeginLongRunningProcess”(假设客户端对象是预先配置的):

for (int i = 0; i < 5; i++)
{
    WCFObject.BeginLongRunningProcess(null, null);
}

Application.Exit();

假设这个长时间运行的方法运行了一个小时。结果是在 WCF 服务器上发生了 5 次异步调用,而 UI 已关闭。

问题是,我如何获得那些正在执行的线程的列表,并取消其中一个?甚至可能吗?

问题:

  1. 我如何获取线程列表
  2. 我如何识别彼此的线程(我可以在调用它们时标记它们吗?)

谢谢

4

1 回答 1

2

在我开始回答之前,我想解决这个问题引入的一些歧义:

WCF,或者更具体地说,承载 WCF 的 Web 应用程序,将创建一个新的服务实例来并发执行任何服务调用,而不管在客户端上创建服务使用者类时是否生成了异步方法。异步方法只是为了客户端的利益,因此可以进行服务调用,客户端可以继续执行,然后可以在以后的任意时间请求调用的结果。(通常,您会执行 MyService.BeginMyMethod 调用,稍后再执行 MyService.EndMyMethod。)

现在为了解决这个问题,我将采用更简单的方法,并假设您希望 WCF 主机跟踪其当前长时间运行的方法。为了让服务了解其长期运行的方法,您只需维护自己的静态列表即可。一个简单的代码示例:

public class Service1 : IService1
{
    public static List<Task> MyRunningTasks = new List<Task>();
    private static object MyRunningTasksLockObject = new object();

    public void StartMyLongRunningMethod()
    {
        var myTracker = new MyProcessTrackingClass()
        {
            OwnerName = HttpContext.Current.User.Identity.Name,
            StartTime = DateTime.Now
        };
        var myAction = new Action<object>(userState => 
            {
                var myActionTracker = (MyProcessTrackingClass)userState;
                for (int i = 0; i < 10; i++)
                {
                    System.Threading.Thread.Sleep(TimeSpan.FromMinutes(1.0));
                    myActionTracker.PercentComplete += 10M;
                }
            });
        var myTask = Task.Factory.StartNew(myAction, myTracker, TaskCreationOptions.LongRunning);
        AddLongRunningMethod(myTask);
        myTask.ContinueWith(t => RemoveLongRunningMethod(t));
    }

    private static void AddLongRunningMethod(Task item)
    {
        lock (MyRunningTasksLockObject)
        {
            MyRunningTasks.Add(item);
        }
    }
    private static void RemoveLongRunningMethod(Task item)
    {
        lock (MyRunningTasksLockObject)
        {
            MyRunningTasks.Remove(item);
        }
    }
}

public sealed class MyProcessTrackingClass
{
    public string OwnerName { get; set; }
    public DateTime StartTime { get; set; }
    public Decimal PercentComplete { get; set; }
}

上面示例中的主体myAction是您的方法逻辑所在的位置(或者您可以从该点调用一个单独的方法)。此外,这种方法还提供了一些其他好处。一方面,服务方法本身只是创建一个Task将完成所有繁重工作的方法,因此该方法实际上会快速向客户端返回响应,因此无论您在客户端创建异步方法还是创建异步方法都没有关系不是。

另一个好处是,由于您的服务知道正在运行的进程,您甚至可以公开另一个允许客户端查询当前长时间运行的进程的服务方法,如下所示:

public IEnumerable<MyProcessTrackingClass> ListLongRunningProcesses()
{
    return MyRunningTasks.Select(t => (MyProcessTrackingClass)t.AsyncState);
}

正如在最后一个示例中所指出的,AsyncState每个属性都Task包含我们的自定义类,作为state创建. 您可以更新以包含您希望与运行方法关联的任何属性。StartNewTaskMyProcessTrackingClass

于 2013-03-06T18:25:36.780 回答