显示试图连接服务器时加载动画
问题描述:
我有一个连接到服务器的简单登录表单。显示试图连接服务器时加载动画
当用户按下登录按钮时,动画加载GIF需要显示,直到连接已建立或失败。
从理论上讲,我做到了:
private void button_login_Click(object sender, EventArgs e)
{
button_login.Text = WORKING;
Loading(ShowMode.show, pictureBox_login_loading);
// send request
client = new TcpClient();
try
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5000);
client.Connect(endPoint);
// send login details .. :)
output = client.GetStream();
writer = new BinaryWriter(output);
reader = new BinaryReader(output);
// write details
writer.Write("login" "|" userID "|" privateName);
}
catch (Exception)
{
MessageBox.Show("Server is down.");
return;
}
finally
{
// Stop loading and return status
button_login.Text = DEFAULT_LOGIN_TEXT;
Loading(ShowMode.hide, pictureBox_login_loading);
}
}
加载的是,图片框的Visible属性设置为Visible
功能。 (我认为这会有所帮助)
问题是:gif只有在button_login_Click
完成其运行后才可见,并且在它看不见之后。
如何使动画gif在执行的行上可见?
答
问题是你不回退到GUI线程,所以没有能力显示你的GIF。
我建议使用BackgroundWorker连接到您的客户端,然后在开始工作之前显示GIF并在工作人员完成的呼叫中停止它。
示例代码(注意,我没有编译这个,因为我没有你的源充足的话):
button_login.Text = WORKING;
Loading(ShowMode.show, pictureBox_login_loading);
// send request
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler((obj, args) =>
{
client = new TcpClient();
try
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5000);
client.Connect(endPoint);
// send login details .. :)
output = client.GetStream();
writer = new BinaryWriter(output);
reader = new BinaryReader(output);
// write details
writer.Write("login" "|" userID "|" privateName);
}
catch (Exception)
{
this.Invoke(new Action(() =>MessageBox.Show("Server is down."));
}
});
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((obj, args) =>
{
button_login.Text = DEFAULT_LOGIN_TEXT;
Loading(ShowMode.hide, pictureBox_login,loading);
});
worker.RunWorkerAsync();
这种方法产生的GUI线程使其能够显示您的GIF并且仍然监控您的连接,并在完成后删除GIF和恢复按钮文本。
答
由于它是一个动画,你可能需要在另一个线程上启动连接,以便UI线程不被阻塞。如果它是静止图像,您可以调用picturebox的Update()
方法来显示它。但是,对于你的情况,这样的事情应该工作:
Thread thread = new Thread(new ThreadStart(delegate
{
Invoke((Action)(()=>{ button_login.Text = WORKING; Loading(ShowMode.show, pictureBox_login_loading); }));
// send request
client = new TcpClient();
try
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5000);
client.Connect(endPoint);
// send login details .. :)
output = client.GetStream();
writer = new BinaryWriter(output);
reader = new BinaryReader(output);
// write details
writer.Write("login" "|" userID "|" privateName);
}
catch (Exception)
{
MessageBox.Show("Server is down.");
return;
}
finally
{
// Stop loading and return status
Invoke((Action)(()=>{ button_login.Text = DEFAULT_LOGIN_TEXT; Loading(ShowMode.hide, pictureBox_login_loading); }));
}
}));
thread.Start();
你也可以使用像讨论的其他答案一个BackgroundWorker,但我倾向于保留更长久运行的任务,比如那些带有进度报告进度酒吧。如果是短期(ish)任务,我通常在.NET 4.0中使用Thread
或Task.Factory.StartNew
。