我正在做一个执行某种扫描的应用程序(它通过一个短列表检查URL的可用性),并根据结果,它添加到一个或另一个列表框。如果存在,则转到lstOK,否则转到lst404。
问题是这些网络检查需要花费时间(特别是当它没问题时),需要花费很长时间,最后在列表框中插入所有项目,而表单“没有响应”并且没有出现任何内容或者可以点击或显示任何互动。
有没有办法让表单仍然可用,列表框可以随时更新?
这应该很简单,我只是不知道(还)
我在Visual Studio中使用C#
- [更新] -
整个url检查在一个单独的函数Start()
答案 0 :(得分:4)
答案 1 :(得分:2)
如果这是执行这些“Web检查”的桌面应用程序,则可以使用BackgroundWorkerThread执行处理,并获得结果。
或者你可以这样做:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace ThreadWithDataReturnExample
{
public partial class Form1 : Form
{
private Thread thread1 = null;
public Form1()
{
InitializeComponent();
thread1 = new Thread(new ThreadStart(this.threadEntryPoint));
Thread1Completed += new AsyncCompletedEventHandler(thread1_Thread1Completed);
}
private void startButton_Click(object sender, EventArgs e)
{
thread1.Start();
//Alternatively, you could pass some object
//in such as Start(someObject);
//With apprioriate locking, or protocol where
//no other threads access the object until
//an event signals when the thread is complete,
//any other class with a reference to the object
//would be able to access that data.
//But instead, I'm going to use AsyncCompletedEventArgs
//in an event that signals completion
}
void thread1_Thread1Completed(object sender, AsyncCompletedEventArgs e)
{
if (this.InvokeRequired)
{//marshal the call if we are not on the GUI thread
BeginInvoke(new AsyncCompletedEventHandler(thread1_Thread1Completed),
new object[] { sender, e });
}
else
{
//display error if error occurred
//if no error occurred, process data
if (e.Error == null)
{//then success
MessageBox.Show("Worker thread completed successfully");
DataYouWantToReturn someData = e.UserState as DataYouWantToReturn;
MessageBox.Show("Your data my lord: " + someData.someProperty);
}
else//error
{
MessageBox.Show("The following error occurred:" + Environment.NewLine + e.Error.ToString());
}
}
}
#region I would actually move all of this into it's own class
private void threadEntryPoint()
{
//do a bunch of stuff
//when you are done:
//initialize object with data that you want to return
DataYouWantToReturn dataYouWantToReturn = new DataYouWantToReturn();
dataYouWantToReturn.someProperty = "more data";
//signal completion by firing an event
OnThread1Completed(new AsyncCompletedEventArgs(null, false, dataYouWantToReturn));
}
/// <summary>
/// Occurs when processing has finished or an error occurred.
/// </summary>
public event AsyncCompletedEventHandler Thread1Completed;
protected virtual void OnThread1Completed(AsyncCompletedEventArgs e)
{
//copy locally
AsyncCompletedEventHandler handler = Thread1Completed;
if (handler != null)
{
handler(this, e);
}
}
#endregion
}
}
答案 2 :(得分:1)
答案 3 :(得分:1)
Application.DoEvents();将完成到目前为止发生的所有事件。
所以在你的循环中,例如,在检查每个网站之后。做Application.DoEvents();
另一方面,如果你只想刷新你的列表框,它将是listboxname.Refresh();
这两个选项,但是在网站被ping时,它仍然会有冻结的时间,除非你做了很多,我不打算这样做。
这两种方法也只使用单个线程并且非常线性
最好的选择是创建一个新线程来进行测试,或者使用可以在单独线程上进行测试的后台工作程序,这样就可以立即处理表单事件而无需等待。
手动控制另一个线程不应该太困难。 这是一个例子。
using System.Threading;
public class MultiThreadingClass
{
private void FunctionForNewThread()
{
//do stuff
}
private void FunctionWithParameter(object param)
{
//Should do checks with typeof() on param before casting
int convertedparam = (int)param;
//do stuff
}
Thread t, t2;
static void Main()
{
ThreadStart ts = new ThreadStart(FunctionForNewThread);
t = new Thread(ts);
t.Start();
int x = 5;
ParameterizedThreadStart pts = new ParameterizedThreadStart(FunctionWithParameter);
t2 = new Thread(pts);
t2.Start(x);
}
}
这里可能需要注意的是,你永远不应该将一个Thread添加为一个会消失的局部变量,因为你只能通过在新线程调用的函数中执行Thread.CurrentThread来获得线程实例。 ,但如果该线程已被锁定,那么你有一点问题:)
要在全局变量中轻松处理Threads,请创建一个线程数组并调用Thread.Abort();在程序关闭时在每个运行的线程上,或在System.Threading中使用ThreadPool类。