我有一项耗时的任务,可以测试几个网络连接。在我下面的例子中,我将它限制在一个连接中。 通常,连接会快速返回,但可能会发生无法建立连接以致套接字超时的情况。在这段时间我想在表单中显示一个“闲人”gif,当连接成功时应用程序应该将表单中的图像更改为某些 绿色检查图标或如果连接失败,应显示红色图标“塞子”。
不知怎的,我无法让闲人的GIF变得可见和动画。要模拟失败的连接,可以输入无效的端口#或不存在的地址。
有什么线索我错过了什么或做错了什么?
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
///
#region BackgroundWorker
private System.ComponentModel.BackgroundWorker backgroundWorker = new System.ComponentModel.BackgroundWorker();
private delegate void SomeLongRunningMethodHandler(object sender, EventArgs e);
#endregion
private System.ComponentModel.IContainer components = null;
Button button,button2;
static Socket socket;
static bool success;
private static bool done;
private Label lbl1;
private Label lbl2;
private TextBox address;
private TextBox port;
private PictureBox p;
private static String port_number,host;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
private void RunTest(object o,EventArgs e)
{
p.Visible = true;
SomeLongRunningMethodHandler synchronousFunctionHandler =
default(SomeLongRunningMethodHandler);
synchronousFunctionHandler =
TestConnection;
synchronousFunctionHandler.Invoke(o, e);
}
private void TestConnection(object o, EventArgs e)
{
host = address.Text;
port_number = port.Text;
if (null != socket)
{
socket.Close();
}
Thread.Sleep(1000);
IPEndPoint myEndpoint = new IPEndPoint(0, 0);
IPHostEntry remoteMachineInfo = Dns.GetHostEntry(host);
IPEndPoint serverEndpoint = new IPEndPoint(remoteMachineInfo.AddressList[0],
int.Parse(port_number));
socket = new Socket(myEndpoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
socket.Connect(serverEndpoint);
success = true;
p.Image = global::BlockingUI.Properties.Resources.accept;
}
catch
{
success = false;
p.Image = global::BlockingUI.Properties.Resources.stopper;
}
done = true;
}
private void ExitApp(object o, EventArgs e)
{
Application.Exit();
}
}
答案 0 :(得分:3)
如果你真的想使用BackgroundWorker
,这个(或接近它的东西)应该指向正确的方向。您正在创建一个BackgroundWorker
对象,但之后无法执行任何操作。不允许BackgroundWorker
个对象访问UI元素,因为它们归UI线程所有,但您可以传入UI值,就像我在这里使用Tuple
一样(您可以创建自己的类来保存)如果您也想要这些值,然后在工作完成后从UI线程修改UI。
private struct ConnectionProperties
{
public string Address;
public string Port;
}
private void RunTest(object o, EventArgs e)
{
BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
worker.RunWorkerCompleted += TestComplete;
worker.DoWork += TestConnection;
p.Visible = true;
//worker.RunWorkerAsync(new Tuple<string, string>(address.Text, port.Text));
worker.RunWorkerAsync(new ConnectionProperties{ Address = address.Text, Port = port.Text });
}
private void TestConnection(object sender, DoWorkEventArgs e)
{
bool success = false;
//var connection = e.Argument as Tuple<string, string>;
var connection = (ConnectionProperties)e.Argument;
if (null != socket)
{
socket.Close();
}
Thread.Sleep(1000);
IPEndPoint myEndpoint = new IPEndPoint(0, 0);
IPHostEntry remoteMachineInfo = Dns.GetHostEntry(connection.Address);
IPEndPoint serverEndpoint = new IPEndPoint(remoteMachineInfo.AddressList[0],
int.Parse(connection.Port));
socket = new Socket(myEndpoint.Address.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
socket.Connect(serverEndpoint);
success = true;
}
catch
{
success = false;
}
e.Result = success;
}
// Define other methods and classes here
private void TestComplete(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error == null)
{
var success = (bool)e.Result;
if (success)
{
p.Image = global::BlockingUI.Properties.Resources.accept;
}
else
{
p.Image = global::BlockingUI.Properties.Resources.stopper;
}
}
else
{
//unexpected error, show message or whatever
}
}
答案 1 :(得分:1)
好吧,我用自己的线程完成了这个。通常,您使用长时间运行的任务运行线程,并在需要时调用Control.Invoke(),其中委托指向将在UI上运行的函数。看起来您正在使用后台工作线程更改UI,这是不允许的。
此外,在Winforms中需要调用Control.Invalidate()来强制重新绘制UI并显示新图标。