对于扫描仪接口,最好将逻辑封装在一个或多个类中,并使设备级的东西远离 UI。
网络连接监视器也是如此;这听起来很复杂,可以进入自己的课程。
如果您正在轮询硬件,实际上使用 aSystem.Threading.Timer
来驱动它可能比使用BackgroundWorker
.
这是一个示例控制台应用程序,它具有基本的实现,其中逻辑被拆分为单独的类。
要看的重要的是Timer
驱动它的 。它将在一个单独的线程上定期回调,并从中调用poll()
. 请注意,因为它在单独的线程中回调,所以在某些情况下您可能需要使用锁定,并且您不能直接从它调用 UI。
对于这个简单的类,bool 正在原子操作中更新,因此我们不需要任何同步。
希望您明白我所说的将多线程逻辑分离到一个单独的类中的意思。
using System;
using System.Threading;
namespace Demo
{
// This represents the interface to the scanner hardware.
sealed class BarcodeScannerDevice
{
int counter;
public bool IsConnected()
{
return (++counter%4) != 0; // Make it change every 4 calls.
}
}
// This class has the responsibility of polling the scanner device to determine its status.
sealed class BarcodeScannerMonitor
{
readonly Timer timer;
readonly BarcodeScannerDevice scanner;
bool isConnected;
public BarcodeScannerMonitor(BarcodeScannerDevice scanner)
{
this.scanner = scanner;
timer = new Timer(poll, null, Timeout.Infinite, Timeout.Infinite);
}
public bool IsConnected
{
get
{
return isConnected;
}
}
public void StopPolling()
{
timer.Change(Timeout.Infinite, Timeout.Infinite);
}
public void StartPolling(TimeSpan pollingInterval)
{
timer.Change(TimeSpan.Zero, pollingInterval);
}
void poll(object state)
{
isConnected = scanner.IsConnected();
}
}
static class BarcodeScannerMonitorFactory
{
// You probably want to encapsulate this kind of coupling and
// keep it away from the UI, so we use a factory.
public static BarcodeScannerMonitor Create()
{
var scanner = new BarcodeScannerDevice();
return new BarcodeScannerMonitor(scanner);
}
}
class Program
{
void run()
{
var scannerStatus = BarcodeScannerMonitorFactory.Create();
scannerStatus.StartPolling(TimeSpan.FromSeconds(1));
while (true)
{
Console.WriteLine("Scanner is " + (scannerStatus.IsConnected ? "connected" : "disconnected"));
Thread.Sleep(500);
}
}
static void Main()
{
new Program().run();
}
}
}
另请注意,我还没有处理计时器。适当的代码应该向BarcodeScannerMonitor
类添加一个Dispose()
处理计时器的方法。
您可能还想为类创建接口并在 UI 中使用这些接口,这有助于单元测试。
最后,您可能会注意到 Microsoft 建议对 Windows 窗体程序使用 Windows 窗体计时器,但我认为对于这种硬件轮询 System.Threading.Timer 更好。