我已经在我的类中实现了IHttpAsyncHandler,以便在后台执行5-6个长时间运行的进程,并在每个任务开始时向客户端确认。
之前我使用了一个会话变量并使用当前任务状态更新它,并在5秒的时间间隔内从jquery向服务器发出异步调用请求以获取当前状态,但是这个实现并不好,因为它不断地向服务器状态。
然后我在我的应用程序中实现了IHttpAsyncHandler,现在服务器本身向客户端发送确认,但根据我的实现,我只能发送一个确认!如果我尝试发送多个,那么它的给定错误为"对象引用未设置为对象的实例"
请查看我的示例代码。
我的代码中的ExecuteFirst()方法可以很好地向客户端发送确认,但ExecuteSecond()不会发送确认给出错误。
我瞪大了很多但没有得到正确的方式向客户发送多个确认。
这是我的示例代码,如果有任何想法,请帮助我。
Javascript
function postRequest(url) {
var url = 'StartLongRunningProcess.ashx?JOBCODE=18'
var xmlhttp = getRequestObject();
xmlhttp.open("POST", url, true);
xmlhttp.onreadystatechange =
function () {
if (xmlhttp.readyState == 4) {
var response = xmlhttp.responseText;
divResponse.innerHTML += "<p>" + response + "</p>";
}
}
xmlhttp.send();
}
function getRequestObject() {
var req;
if (window.XMLHttpRequest && !(window.ActiveXObject)) {
try {
req = new XMLHttpRequest();
}
catch (e) {
req = false;
}
}
else if (window.ActiveXObject) {
try {
req = new ActiveXObject('Msxml2.XMLHTTP');
}
catch (e) {
try {
req = new ActiveXObject('Microsoft.XMLHTTP');
}
catch (e) {
req = false;
}
}
}
return req;
}
StartLongRunningProcess.ashx.cs
public class StartLongRunningProcess: IHttpAsyncHandler, IRequiresSessionState
{
private AsyncRequestResult _asyncResult;
public void ProcessRequest(HttpContext context) {}
public bool IsReusable
{
get { return true;}
}
public IAsyncResult BeginProcessRequest(HttpContext context, System.AsyncCallback cb, object extraData)
{
int32 jobCode= convert.ToInt32(context.Request["JOBCODE"]);
_asyncResult = new AsyncRequestResult(context, cb, jobCode);
if(jobCode==18)
{
StartProcess18()
}
else
{
//StartProcessOther()
}
}
private StartProcess18()
{
var task1= new Task(() =>
{
ExecuteFirst();
});
var task2 = task1.ContinueWith((t1) =>
{
ExecuteSecond();
}, TaskContinuationOptions.OnlyOnRanToCompletion);
task1.Start();
}
private ExecuteFirst()
{
//notify to client that this job has been started
_asyncResult.CurrentContext.Response.Write("First task has been started");
_asyncResult.Notify();
// Above line of code successfully send a acknowledgement to client
//Doing some long running process
}
private ExecuteSecond()
{
//notify to client that this job has been started
_asyncResult.CurrentContext.Response.Write("Second task has been started");
// Above line of code giving error and if I skip it and call Notify() this also does not work.
_asyncResult.Notify();
//Doing some long running process
}
public void EndProcessRequest(IAsyncResult result)
{
}
}
AsyncRequestResult.cs
public class AsyncRequestResult : IAsyncResult
{
private HttpContext context;
private AsyncCallback callback;
private ManualResetEvent completeEvent = null;
private object data;
private object objLock = new object();
private bool isComplete = false;
public AsyncRequestResult(HttpContext ctx, AsyncCallback cb, object d)
{
this.context = ctx;
this.callback = cb;
this.data = d;
}
public HttpContext Context
{
get { return this.context; }
}
public void Notify()
{
//isComplete = true;
lock(objLock)
{
if(completeEvent != null)
{
completeEvent.Set();
}
}
if (callback != null)
{
callback(this);
}
}
public object AsyncState
{
get { return this.data; }
}
public bool CompletedSynchronously
{
get { return false; }
}
public WaitHandle AsyncWaitHandle
{
get
{
lock(objLock)
{
if (completeEvent == null)
completeEvent = new ManualResetEvent(false);
return completeEvent;
}
}
}
public bool IsCompleted
{
get { return this.isComplete; }
}
}
答案 0 :(得分:1)
HttpContext.Current
才为空。
正在运行的延续任务很可能在ThreadPool
线程上运行,而HttpContext.Current
没有流向延续,因此它为空。
尝试将TaskScheduler设置为TaskScheduler.FromCurrentSynchronizationContext()
,以便在相同的上下文中执行它。
private StartProcess18()
{
var task1= new Task(() =>
{
ExecuteFirst();
});
var task2 = task1.ContinueWith((t1) =>
{
ExecuteSecond();
}, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());
task1.Start();
}