Как асинхронно вызвать функцию в asp.net?или любое другое решение для достижения цели? - PullRequest
0 голосов
/ 07 сентября 2011

Цель функции - заполнить поле from (со стороннего веб-сайта), нажать кнопку отправки и получить html-источник отправленной страницы результатов.Эту задачу необходимо выполнить по событию нажатия кнопки в asp.net.Если функция возвращает 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 ]

3 голосов
/ 07 сентября 2011

Вот некоторые классы, используемые при реализации длинного опроса с использованием HttpHandlers.Я использую это решение для операций, которые ДОЛЖНЫ завершаться.Есть в основном 6 классов (см. Ниже).Некоторые из этих классов могут оказаться ненужными для ВАШИХ целей, но они имеют смысл для моих.Они «в основном» были продезинфицированы для вас.

  1. Контроллер : Обрабатывает действия, необходимые для создания правильного ответа (операции с БД и т. Д.)
  2. Процессор : управляет асинхронным взаимодействием с самой веб-страницей
  3. IAsynchProcessor : Служба обрабатывает экземпляры, которые реализуют этот интерфейс
  4. Sevice : Обрабатывает объекты запроса, которые реализуют IAsynchProcessor
  5. Запрос : Оболочка IAsynchProcessor, содержащая ваш ответ (объект)
  6. Ответ : Содержит пользовательские объекты или поля

Если вам нужна помощь с комментарием надстройки JavaScript или HTML ниже ... Я напишу кое-что для вас.

HTTP HANDLERS:

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 голос
/ 07 сентября 2011

Ознакомьтесь с этой статьей, в которой описывается, как выполнять метод асинхронно, и используется обработчик событий, который запускается после завершения асинхронного вызова метода.

http://www.csharp -examples.net / создать асинхронный-метод /

Вот черновик того, как бы вы применили содержание статьи в вашей ситуации. Я не проверял код, поэтому он может быть не идеальным, но он должен быть близок.

Вам необходимо импортировать следующие пространства имен:

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
...