是否可以/建议在Web浏览器控件中使用后台工作线程?
我正在创建一个搜索谷歌搜索关键字的机器人,然后检查前10页中的网站,看看网站是否排名.
用户最多可以提供20个站点进行检查,并且可以使用代理.理想情况下,我希望一次有5个线程工作.
可能吗?我可能听说过WebBrowser控件和线程存在问题.
我想制作3个线程,每个线程运行WebBroswer控件.所以我想使用ThreadPool让事情变得简单.
for(int i = 0;i < 3;i++)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(gotoWork), i));
}
WaitAll(waitHandles);
Run Code Online (Sandbox Code Playgroud)
....../
void gotoWork(object o)
{
string url = String.Empty;
int num = (int)o;
switch(num)
{
case 0:
url = "google.com";
break;
case 1:
url = "yahoo.com";
break;
case 2:
url = "bing.com";
break;
}
WebBrowser w = new WebBrower();
w.Navigate(url);
}
Run Code Online (Sandbox Code Playgroud)
但是我得到一个错误,说我需要一个ThreadPool永远不会的STA线程.在尝试这种方法之前,我试过这个.
Thread[] threads = Thread[3];
for(int i = 0;i < 3;i++)
{
threads[i] = new Thread(new ParameterizedStart(gotoWork);
threads[i] = SetApartmentState(ApartmentState.STA); //whoo hoo
threads[i] = Start();
} …Run Code Online (Sandbox Code Playgroud) 我有这个简单的代码:
public void Run()
{
var invokerThread = new Thread(new ThreadStart(RunOnBackground));
invokerThread.Start();
}
private void RunOnBackground()
{
Trace.WriteLine("hi");
...
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,当运行此代码(来自第三方进程)时,线程并没有真正运行.在进程资源管理器和VS调试器中,我看到线程已创建且其状态为"正在运行".
主线程的公寓是STA,我在内部线程上尝试了STA和MTA.
当我Run()在最后添加到方法时invokerThread.Join();,线程确实运行.但话说回来并没有真正帮助.
我错过了什么?
编辑:以下是有关代码托管的更多信息 -
Run() 方法是通过COM interop从一个进程调用的,该进程也是托管可执行程序集(使用COM互操作的原因是因为系统中的所有其他组件都是本机的).
该方法RunOnBackground()在跟踪之后包括一些代码,并且通常其执行持续10-20秒,包括启动另一个进程并等待其终止.此外,我在代码中还有一些其他区域,我将一些调试信息写入Trace.在调试代码时,Run()像往常一样运行并且在invokerThread.Start();invokerThread的状态为"Running"之后(尽管RunOnBackground()方法中的断点不会停止).
当我添加invokerThread.Join()在结束Run()方法调试器去RunOnBackground() 后的Join().
任何人都知道使用System.Windows.Forms.WebBrowser对象的教程?看了一眼但却找不到一个.到目前为止我的代码是(非常复杂):
System.Windows.Forms.WebBrowser b = new System.Windows.Forms.WebBrowser();
b.Navigate("http://www.google.co.uk");
Run Code Online (Sandbox Code Playgroud)
但它实际上并没有导航到任何地方(iebUrl为null,b .Document为null等)
谢谢
我有一个带有嵌入式Web浏览器的C#.NET 3.5应用程序.浏览器旨在指向远程站点(而不是本地的任何东西).一切正常,但当页面响应缓慢时,这会导致整个应用程序无响应,直到页面加载完毕.
我不介意浏览器在做它的事情时没有反应,但是应用程序也远非理想.
有没有好办法防止这种情况发生?在单独的线程上运行WebBrowser是否有益 - 这有点超出我的技能组合,我不认为WebBrowser控件真的喜欢多线程?但如果需要,我可以学习.
我在C#-Program中遇到了WebBrowsing自动化的问题.我之前使用过代码来获取BHO,并且它正在运行.但在纯粹的c#程序中,似乎存在某种僵局.我已经指示我的程序点击搜索按钮,然后等待(通过手动重新发送)文档完成信号.但是现在似乎在ManualResetEvent发出超时信号之前不会处理点击搜索按钮.然后单击,并且还会触发DocumentComplete-Event.
对于该程序的结构:WebBrowser-Control是WindowsForm的一部分.WebBrowser控件传递给运行Thread的Class.该类再次将控件传递给另一个类,其中根据加载的webbrowser编程具体行为.
所以在Code中这样看起来:
线程的设置
_runner = new Thread(runner);
_runner.SetApartmentState(ApartmentState.STA);
_runner.IsBackground = true;
_runner.Start();
Run Code Online (Sandbox Code Playgroud)用流道法加工
b.placeTipp(workStructure);
Run Code Online (Sandbox Code Playgroud)PlaceTipp方法
public void placeTipp(ref OverallTippStructure tipp)
{
_expectedUrl = String.Empty;
_betUrl = String.Empty;
_status = BookieStatusType.CHECKLOGIN;
while (true)
{
_mreWaitForAction.Reset();
checkIETab();
switch (_status)
{
case BookieStatusType.REQUESTWEBSITE:
ConsoleWriter.writeToConsole(String.Format("Bookie {0}: Keine IE-Tab vorhanden. Fordere eine an", this.BookieName));
//if (RequestIETabEvent != null)
// RequestIETabEvent(this, new EventArgs());
_status = BookieStatusType.NAVIGATETOWEBSITE;
_mreWaitForAction.Set();
break;
case BookieStatusType.NAVIGATETOWEBSITE:
_webBrowser.Navigate(@"http://www.nordicbet.com");
break;
case BookieStatusType.CHECKLOGIN:
checkLogin();
break;
case BookieStatusType.LOGINNEEDED:
doLogin();
break;
case BookieStatusType.LOGGEDIN:
_status = BookieStatusType.SEARCHTIPP; …Run Code Online (Sandbox Code Playgroud)我有一个url列表,我需要导航它们.如何确保每个网址都会调用DocumentCompleted事件?我已经尝试创建许多线程并尝试使用单个线程,但应用程序仍然没有为每个URL触发事件DocumentCompleted.
有没有办法在url列表中创建一个循环并让它们调用DocumentCompleted,直到线程调用下一个url?
我看到了一些围绕这个主题的讨论,并得出结论:这是不可能的。我应该使用线程,将其设为 STA,当我需要返回结果时,将主线程与创建的线程连接起来。这可以工作,但它不是一个理想的解决方案,因为使用委托我可以实现纯异步行为(使用回调)。所以,首先——就在我开始实现我自己的 Future 类(如 Java 中)之前;有没有更好的方法使用委托来实现这一目标?
private delegate String DelegateFoo(String[] input);
private String Foo(String[] input){
// do something with input
// this code need to be STA
// below code throws exception .. that operation is invalid
// Thread.CurrentThread.SetApartmentState(ApartmentState.STA)
return "result";
}
private void callBackFoo(IAsyncResult iar){
AsyncResult result = (AsyncResult)iar;
DelegateFoo del = (DelegateFoo)result.AsyncDelegate;
String result = null;
try{
result = del.EndInvoke(iar);
}catch(Exception e){
return;
}
DelegateAfterFooCallBack callbackDel = new DelegateAfterFooCallBack (AfterFooCallBack);
// call code which should execute in the …Run Code Online (Sandbox Code Playgroud) 我正在使用中所示的技术
尝试获取网页的屏幕抓取我已经能够获得以下代码,以便在WebBrowser控件放置在a上时成功工作WinForm.但是,当在线程内运行时,它会通过提供桌面的任意图像而失败.
Thread browserThread = new Thread(() =>
{
WebBrowser br = new WebBrowser();
br.DocumentCompleted += webBrowser1_DocumentCompleted;
br.ProgressChanged += webBrowser1_ProgressChanged;
br.ScriptErrorsSuppressed = true;
br.Navigate(url);
Application.Run();
});
browserThread.SetApartmentState(ApartmentState.STA);
browserThread.Start();
private Image TakeSnapShot(WebBrowser browser)
{
int width;
int height;
width = browser.ClientRectangle.Width;
height = browser.ClientRectangle.Height;
Bitmap image = new Bitmap(width, height);
using (Graphics graphics = Graphics.FromImage(image))
{
Point p = new Point(0, 0);
Point upperLeftSource = browser.PointToScreen(p);
Point upperLeftDestination = new Point(0, 0);
Size blockRegionSize = browser.ClientRectangle.Size; …Run Code Online (Sandbox Code Playgroud) c# multithreading screen-scraping apartments webbrowser-control
我对用 MessageLoopWorker 包装的 WebBrowser 控件进行了一些测试,如下所述:WebBrowser Control in a new thread
但是当另一个测试创建用户控件或表单时,测试会冻结并且永远不会完成:
[Test]
public async Task WorksFine()
{
await MessageLoopWorker.Run(async () => new {});
}
[Test]
public async Task NeverCompletes()
{
using (new Form()) ;
await MessageLoopWorker.Run(async () => new {});
}
// a helper class to start the message loop and execute an asynchronous task
public static class MessageLoopWorker
{
public static async Task<object> Run(Func<object[], Task<object>> worker, params object[] args)
{
var tcs = new TaskCompletionSource<object>();
var thread = …Run Code Online (Sandbox Code Playgroud) c# ×10
.net ×3
browser ×2
apartments ×1
async-await ×1
deadlock ×1
delegates ×1
mta ×1
nunit ×1
sta ×1
threadpool ×1
url ×1
winforms ×1