【发布时间】:2012-07-12 20:30:35
【问题描述】:
我有一个 WPF 表单,其中包含一个按钮和一个进度条元素。当我单击该按钮时,它会从另一个类调用一个函数,该函数启动一个后台工作程序,该工作程序负责通过串行端口读取/写入数据到我正在为其编写 Windows 界面的设备。
之前我在使用一个新线程,但我决定尝试一个后台工作人员,但仍然没有运气。
发生的情况是我单击按钮,进度条保持在 0%,直到我的耗时(10 多秒)for 循环完成,然后进度跳到 100%
任何帮助表示赞赏,在此先感谢。下面是我的接口逻辑代码:
private void connectButton_Click(object sender, RoutedEventArgs e) //Connect button clicked
{
if (!Global.isConnected)
{
device.readValues((string)portsOpen.SelectedValue, connectProgress);
portsOpen.IsEnabled = false;
connectButton.Content = "Disconnect";
}
else
{
device.disconnect();
portsOpen.IsEnabled = true;
connectButton.Content = "Connect";
}
}
下面是我的附加课程的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Windows.Controls;
using System.ComponentModel;
namespace lookoutSecurity
{
class agentRadioRead
{
/*Local Variable Declarations*/
SerialPort sp;
BackgroundWorker worker;
int attempt = 0;
public string[] populateAvailablePorts() //Returns string array of open ports
{
String[] portsAvailable = SerialPort.GetPortNames();
return portsAvailable;
}
public void readValues(string selectedPort, ProgressBar progressBar) //Function that sets up serial port and background worker
{
sp = new SerialPort(selectedPort, 9600, Parity.None, 8, StopBits.One);
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.ProgressChanged += new ProgressChangedEventHandler(worker_ProgressChanged);
worker.RunWorkerAsync(progressBar);
}
private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) //Update user interface with current percentage
{
ProgressBar progressBar = e.UserState as ProgressBar;
App.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Send,
new Action(
delegate()
{ progressBar.Value = e.ProgressPercentage; }));
}
private void worker_DoWork(object sender, DoWorkEventArgs e) //Initial starting point for reading data
{
startRead((ProgressBar)e.Argument);
}
private string sendInitial() //Sends ? and returns init ASUTTON
{
string init = "";
sp.Write("?");
for (int i = 0; i < 7; i++)
{
try
{
init += sp.ReadByte().ToString();
}
catch
{
break;
}
}
return init;
}
private void startRead(ProgressBar progressBar) //Initializes data send and receive
{
sp.ReadTimeout = 5000;
sp.Open();
string init = sendInitial();
if (init == Global.AGENT_RADIO)
{
sp.Write(Global.READ_VALUES, 0, Global.READ_VALUES.Length);
byte key = (byte)sp.ReadByte();
if (Global.START_COMMAND == key)
{
for (int i = 1; i < 2247; i++)
{
object progressBarObject = new object();
progressBarObject = progressBar;
int progress = (i / 2246) * 100;
worker.ReportProgress(progress, progressBarObject);
readData(i, progressBar);
sp.Write(Global.GO_AHEAD, 0, Global.GO_AHEAD.Length);
sp.DiscardInBuffer();
sp.DiscardOutBuffer();
}
}
else
{
System.Windows.MessageBox.Show("Connection Failed - Invalid Key: " + key);
sp.Close();
}
}
else
{
sp.Close();
if (attempt < 3)
{
attempt++;
startRead(progressBar);
}
else
{
System.Windows.MessageBox.Show("Connection Failed - Not Agent Radio: " + init);
}
}
}
private void readData(int iteration, ProgressBar progress) //Reads data for current iteration
{
byte value = 0;
try
{
value = (byte)sp.ReadByte();
}
catch
{
sp.Close();
Global.isConnected = false;
if (attempt < 3)
{
attempt++;
startRead(progress);
}
else
{
System.Windows.MessageBox.Show("Read Timeout - Value Number: " + iteration);
App.Current.Shutdown();
}
}
if (iteration > 0 && iteration < 385) //read schedule
{
double pos = (iteration - 1) / 48;
int i = (int)Math.Floor(pos);
int j = (iteration - 1) - (i * 48);
Live.schedule[i, j] = value;
}
if (iteration > 384 && iteration < 1285) //read alarm history
{
double pos = (iteration - 385) / 9;
int i = (int)Math.Floor(pos);
int j = (iteration - 385) - (i * 9);
Live.alarms[i, j] = value;
}
if (iteration > 1284 && iteration < 1345) //read error log
{
double pos = (iteration - 1285) / 6;
int i = (int)Math.Floor(pos);
int j = (iteration - 1285) - (i * 6);
Live.errors[i, j] = value;
}
if (iteration > 1344 && iteration < 1945) //read voltage history
{
double pos = (iteration - 1345) / 6;
int i = (int)Math.Floor(pos);
int j = (iteration - 1345) - (i * 6);
Live.voltage[i, j] = value;
}
if (iteration > 1944 && iteration < 1973) //read holidays
{
Live.holidays[iteration - 1945] = value;
}
if (iteration > 1972 && iteration < 2168) //read message sequences
{
double pos = (iteration - 1973) / 15;
int i = (int)Math.Floor(pos);
int j = (iteration - 1973) - (i * 15);
Live.messages[i, j] = value;
}
if (iteration > 2167 && iteration < 2196) //read message info
{
Live.recordings[iteration - 2168] = value;
}
if (iteration > 2195 && iteration < 2246) //read sysval
{
Live.sysval[iteration - 2196] = value;
}
if (iteration == 2246 && value == Global.FINISH_COMMAND)
{
System.Windows.MessageBox.Show("All values from the device have been received.", "Data Received", System.Windows.MessageBoxButton.OK, System.Windows.MessageBoxImage.Information);
Global.isConnected = true;
}
}
public void disconnect() //Disconnects device
{
if (Global.isConnected == true)
{
sp.Write(Global.EXIT_PROGRAM, 0, Global.EXIT_PROGRAM.Length);
Global.isConnected = false;
}
}
}
}
【问题讨论】:
-
您可能希望使用
(ProgressBar)e.UserState而不是e.UserState as ProgressBar。as运算符是 VB.NET 的一个转折点,恕我直言,不应在 C# 中使用... -
@ColeJohnson 你能解释一下为什么
as不应该在 C# 中使用吗? -
@ColeJohnson:as 没什么问题。这是非常好的 C#。
-
@ColeJohnson 我不同意它不应该被使用;
as适用于您不确定演员表是否会成功的情况(但如果成功了,我想采取某些行动。)不过,我实际上同意这种情况,因为演员表总是会成功。 -
虽然您可以将
i转换为浮点类型,但您也可以先进行乘法运算并避免转换/转换问题:int progress = (i * 100) / 2246;
标签: c# wpf multithreading progress-bar backgroundworker