该功能的目标是填充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
答案 0 :(得分:3)
以下是使用HttpHandlers实现长轮询的一些类。我将此解决方案用于需要很长时间才能完成的操作。基本上有6个类(见下文)。为了您的目的,其中一些类可能最终不需要,但它们对我来说是有道理的。这些“大部分”已经为您消毒了。
如果您需要有关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