我有一个UI,它调用一个名为'LongRunningProcess'的WCF方法--WCF已经生成了异步方法'BeginLongRunningProcess'(假设客户端对象是预配置的):
for (int i = 0; i < 5; i++)
{
WCFObject.BeginLongRunningProcess(null, null);
}
Application.Exit();
假设这个长时间运行的方法运行一个小时。结果是在WCF服务器上发生了5次异步调用,而UI已关闭。
问题是,如何获取执行线程的列表,并取消其中一个?它甚至可能吗?
问题:
由于
答案 0 :(得分: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
的{{1}}属性包含我们的自定义类,作为Task
方法的state
参数传入创建了StartNew
。您可以更新Task
以包含您希望与正在运行的方法关联的任何属性。