如何异步调用asp.net中的函数?或达到目标的任何其他解决方案?

时间:2011-09-07 17:30:22

标签: asp.net asynchronous httphandler

  

该功能的目标是填充from(来自第三方网站)并单击提交按钮并获取提交结果页面的html源。这个任务需要在asp.net中按钮的click事件上完成。如果函数返回true,则在最后执行一些sql任务。我在asp.net上读到了异步处理程序,但是真正的初学者并不确定在asp.net中模拟这种类型的任务是什么最佳解决方案。

Protected Sub lbtnSave_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles lbtnSave.Click
             If  CrawlWebSite() then
                'Save
             End If
         End Sub

Private Function CrawlWebSite() As Boolean
            Dim objBrowser = CreateObject("InternetExplorer.Application")
            Dim url As String = "https://test.com/Search.do?subAction=reset&searchType=ind"
            With objBrowser
                .navigate(url)
                System.Threading.Thread.Sleep(1000)

                Dim StartTime As DateTime
                Dim ElapsedTime As TimeSpan
                Dim bLong As Boolean = False
                StartTime = Now
                Do While .busy = True
                    ElapsedTime = Now().Subtract(StartTime)
                    If (ElapsedTime.TotalSeconds Mod 60) >= 55 Then
                        bLong = True
                        Exit Do
                    End If
                    System.Threading.Thread.Sleep(1000)
                Loop

                If bLong = True Then
                    PageName.Alert(Page, "There is a delay retrieving the website for checking NPI. Please try again.")
                    Return False
                End If

                .document.getElementById("lastname").Value = txtLastName.Text.Trim
                .document.getElementById("searchNpi").Value = txtUPIN.Text.Trim
                .document.getElementsByTagName("input").item(7).click()

                System.Threading.Thread.Sleep(1000)

                bLong = False
                StartTime = Now
                Do While .busy = True
                    'There is a delay retrieving the website. Continue ?
                    ElapsedTime = Now().Subtract(StartTime)
                    If (ElapsedTime.TotalSeconds Mod 60) >= 50 Then
                        bLong = True
                        Exit Do
                    End If
                    System.Threading.Thread.Sleep(1000)
                Loop

                If bLong = True Then
                    PageName.Alert(Page, "There is a delay retrieving the website. Please try again.")
                    Return False
                End If

                If .document.getElementById("lastname") Is Nothing Then
                    'We have result
                    Return True
                Else
                    PageName.Alert(Page, "Attention: No matching records found.")
                    Return False
                End If

            End With

        End Function

2 个答案:

答案 0 :(得分:3)

以下是使用HttpHandlers实现长轮询的一些类。我将此解决方案用于需要很长时间才能完成的操作。基本上有6个类(见下文)。为了您的目的,其中一些类可能最终不需要,但它们对我来说是有道理的。这些“大部分”已经为您消毒了。

  1. 控制器:处理创建有效响应所需的操作(数据库操作等)。
  2. 处理器:管理与网页(本身)的异步通信
  3. IAsynchProcessor :服务处理实现此接口的实例
  4. 服务:处理实现IAsynchProcessor的请求对象
  5. 请求:包含响应(对象)的IAsynchProcessor包装器
  6. 响应:包含自定义对象或字段
  7. 如果您需要有关JavaScript或HTML插件的帮助,请在下面添加评论...我会为您写一些内容。

    HTTP处理程序:

    using System;
    using System.Configuration;
    using System.Web;
    using System.Web.Script.Serialization;
    using System.Web.Services;
    using System.Web.SessionState;
    
    namespace Concept.LongPolling.Handlers
    {
        /// <summary>
        /// Summary description for Controller
        /// </summary>
        public class Controller : IHttpHandler, IReadOnlySessionState
        {
            #region CONSTRUCTORS
            #endregion
    
            #region PROPERTIES
    
            /// <summary>Gets a Boolean value indicating that another request can use the current instance of the DefaultHttpHandler class.</summary>
            /// <remarks>Returning true makes the same AsyncHttpHandler object be used for all requests.</remarks>
            /// <remarks>Returning false here makes ASP.Net create object per request.</remarks>
            public bool IsReusable { get { return true; } }
    
            #endregion
    
            #region METHODS
    
            /// <summary>Enables synchronous processing of HTTP Web requests</summary>
            /// <param name="context">An HttpContext object that provides references to the intrinsic server objects</param>
            /// /// <remarks>This is where you would send commands to the controller that would affect processing in some manner.</remarks>
            public void ProcessRequest(HttpContext context)
            {
                throw new NotImplementedException();
            }
    
            /// <summary>Creates the response object which is serialized back to the client</summary>
            /// <param name="response"></param>
            public static Response CreateResponse(Response response)
            {
                try
                {
                    response.Generate();
                }
                catch (System.Exception ex)
                {
                    response.SessionValid = false;
                }
    
                return response;
            }
    
            #endregion
        }
    }
    
    using System;
    using System.Configuration;
    using System.Web;
    using System.Web.Script.Serialization;
    using System.Web.Services;
    using System.Web.SessionState;
    using Concept.LongPolling.LongPolling;
    
    namespace Concept.LongPolling.Handlers
    {
        /// <summary>
        /// Summary description for Processor
        /// </summary>
        public class Processor : IHttpHandler, IHttpAsyncHandler, IReadOnlySessionState
        {
            #region CONSTRUCTORS
            #endregion
    
            #region PROPERTIES
    
            /// <summary>Gets a Boolean value indicating that another request can use the current instance of the DefaultHttpHandler class.</summary>
            /// <remarks>Returning true makes the same AsyncHttpHandler object be used for all requests.</remarks>
            /// <remarks>Returning false here makes ASP.Net create object per request.</remarks>
            public bool IsReusable { get { return false; } }
    
            #endregion
    
            #region METHODS
    
            /// <summary>Enables synchronous processing of HTTP Web requests</summary>
            /// <param name="context">An HttpContext object that provides references to the intrinsic server objects</param>
            public void ProcessRequest(HttpContext context)
            {
                throw new NotImplementedException();
            }
    
            #region IHttpAsyncHandler Members
    
            /// <summary>Enables asynchronous processing of HTTP Web requests</summary>
            /// <param name="context">An HttpContext object that provides references to the intrinsic server objects</param>
            /// <param name="cb">The method to call when the asynchronous method call is complete. If callback is null, the delegate is not called.</param>
            /// <param name="extraData"></param>
            /// <returns>Any state data that is needed to process the request.</returns>
            public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
            {
                Int32 someValueYouLikeToSendInYourClass = Convert.ToInt32(context.Request["Number"]);
    
                Request request = new Request(cb, context);
                request.Response.Number = someValueYouLikeToSendInYourClass;
    
                Service.Singleton.AddRequest(request);
    
                return request;
            }
    
            /// <summary>Provides an end method for an asynchronous process.</summary>
            /// <param name="result">An object that contains information about the status of the process.</param>
            public void EndProcessRequest(IAsyncResult result)
            {
                Request request = result as Request;
                JavaScriptSerializer serializer = new JavaScriptSerializer();
    
                request.HttpContext.Response.ContentType = "text/json";
                request.HttpContext.Response.Write(serializer.Serialize(request.Response));
                request.HttpContext.Response.End();
            }
    
            #endregion
    
            #endregion
        }
    }
    

    支持课程:

    using System;
    using System.Runtime.InteropServices;
    
    namespace Concept.LongPolling.LongPolling
    {
        /// <summary>Represents the executable instance of an asynchronous operation.</summary>
        [ComVisible(true)]
        public interface IAsynchProcessor : IAsyncResult
        {
            /// <summary>
            /// Gets a value that indicates whether the operation completed sucessfully.
            /// </summary>
            /// <returns>true if the operation completed sucessfully; otherwise, false.</returns>
            bool ProcessRequest();
        }
    }
    
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Threading;
    
    namespace Concept.LongPolling.LongPolling
    {
        public sealed class Service
        {
            #region CONSTRUCTORS
    
            private Service()
            {
                requests = new List<IAsynchProcessor>();
                backgroundThread = new Thread(new ThreadStart(MainLoop));
                backgroundThread.IsBackground = true;
                backgroundThread.Start();
            }
    
            #endregion
    
            #region PROPERTIES
    
            private static Service singleton;
            private Thread backgroundThread;
            private List<IAsynchProcessor> requests;
            static readonly object padlock = new object();
    
            public static Service Singleton
            {
                get
                {
                    if (_singleton == null)
                        lock (_padlock)
                        {
                            if (_singleton == null)
                                _singleton = new Service();
                        }
    
                    return _singleton;
                }
            }
    
            #endregion
    
            #region METHODS
    
            private void MainLoop()
            {
                while (true)
                {
                    foreach (IAsynchProcessor request in requests.ToArray())
                    {
                        if (request.ProcessRequest())
                            requests.Remove(request);
                    }
                    Thread.Sleep(500);
                }
            }
    
            public void AddRequest(IAsynchProcessor request)
            {
                lock (padlock)
                {
                    requests.Add(request);
                }
            }
    
            #endregion
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Concept.LongPolling.Business;
    using System.Data;
    
    namespace Concept.LongPolling.Handlers
    {
        public class Response
        {
            #region CONSTRUCTORS
    
            public Response()
            {
                SessionValid = true;
                Exception = String.Empty;
            }
    
            #endregion
    
            #region PROPERTIES
    
            public const int TimeOffset = 120;
    
            public Int32 Number { get; set; }
            public bool SessionValid { get; set; }
            public String Exception { get; set; }
    
            #endregion
    
            #region METHODS
    
            public void Generate()
            {
                // do some desired operation
                Number += 1;
            }
    
            #endregion
        }
    }
    
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Concept.LongPolling.LongPolling;
    
    namespace Concept.LongPolling.Handlers
    {
        public class Request : IAsynchProcessor
        {
            #region CONSTRUCTORS
    
            public Request(AsyncCallback callback, HttpContext context)
            {
                asyncCallback = callback;
                httpContext = context;
                createdTime = DateTime.Now;
    
                Response = new Response();
            }
    
            #endregion
    
            #region PROPERTIES
    
            public const int TimeoutSeconds = 15;
    
            private AsyncCallback asyncCallback;
            private HttpContext httpContext;
            private DateTime createdTime;
    
            public bool TimedOut
            {
                get
                {
                    return ((DateTime.Now - createdTime).TotalSeconds >= TimeoutSeconds);
                }
            }
    
            public Response Response { get; set; }
    
            #region IAsyncResult Members
    
            public HttpContext HttpContext
            {
                get
                {
                    return httpContext;
                }
            }
            public object AsyncState { get; set; }
    
            System.Threading.WaitHandle IAsyncResult.AsyncWaitHandle
            {
                get { throw new NotImplementedException(); }
            }
    
            bool IAsyncResult.CompletedSynchronously
            {
                get { return false; }
            }
    
            public bool IsCompleted
            {
                get { return isCompleted; }
                set
                {
                    if (!value) return;
    
                    this.isCompleted = true;
                    asyncCallback(this);
                }
            }
            bool isCompleted = false;
    
            #endregion
    
            #endregion
    
            #region METHODS
    
            public bool ProcessRequest()
            {
                this.Response = Controller.CreateResponse(this.Response);
                this.IsCompleted = true;
    
                return this.IsCompleted;
            }
    
            #endregion
        }
    }
    

答案 1 :(得分:1)

看看这篇文章,它描述了如何异步执行方法,并使用在异步方法调用完成时触发的事件处理程序。

http://www.csharp-examples.net/create-asynchronous-method/

以下是如何在您的情况下应用文章内容的草稿。我没有测试过代码,所以它可能不完美,但它应该很接近。

您需要导入以下命名空间:

using System.Threading;
using System.ComponentModel;
using System.Runtime.Remoting.Messaging;

这是粗略的实施:

//boolean flag which indicates whether the async task is running
private bool crawling = false;

private delegate bool CrawlWebsiteDelegate();

private bool CrawlWebsite()
{
    //crawl the website

    return false;
}

protected void Button1_Click(object sender, EventArgs e)
{
    CrawlWebsiteDelegate worker = new CrawlWebsiteDelegate(CrawlWebsite);
    AsyncCallback completedCallback = new AsyncCallback(CrawlWebsiteCompletedCallback);

    if (!crawling)
    {
        worker.BeginInvoke(completedCallback, AsyncOperationManager.CreateOperation(null));
        crawling = true;
    }
}

private void CrawlWebsiteCompletedCallback(IAsyncResult ar)
{
    //get the original worker delegate and the AsyncOperation instance
    CrawlWebsiteDelegate worker = (CrawlWebsiteDelegate)((AsyncResult)ar).AsyncDelegate;

    //finish the asynchronous operation
    bool success = worker.EndInvoke(ar);
    crawling = false;

    if (success)
    {
        //perform sql tasks now that crawl has completed
    }
}

编辑:这是VB.NET中的代码 - 并非所有语法都正确

Private crawling As Boolean = False    
Private Delegate Function CrawlWebsiteDelegate() As Boolean

Private Function CrawlWebsite() As Boolean
    Return False    
End Function

Protected Sub Button1_Click(sender As Object, e As EventArgs)
    Dim worker As New CrawlWebsiteDelegate(AddressOf CrawlWebsite)
    Dim completedCallback As New AsyncCallback(AddressOf CrawlWebsiteCompletedCallback) 
    If Not crawling Then
        worker.BeginInvoke(completedCallback, AsyncOperationManager.CreateOperation(Nothing))
        crawling = True
    End If  
End Sub

Private Sub CrawlWebsiteCompletedCallback(ar As IAsyncResult)
    Dim worker As CrawlWebsiteDelegate = DirectCast(DirectCast(ar, AsyncResult).AsyncDelegate, CrawlWebsiteDelegate)
    Dim success As Boolean = worker.EndInvoke(ar)
    crawling = False        
    If success Then
        DoSomeSqlTasks()
    End If
End Sub