Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 我必须在哪里抛出异常以防止任务中无休止的等待_C#_Serial Port - Fatal编程技术网

C# 我必须在哪里抛出异常以防止任务中无休止的等待

C# 我必须在哪里抛出异常以防止任务中无休止的等待,c#,serial-port,C#,Serial Port,我有一个硬件设备通过串行端口连接到我的电脑,当我向它发送信号时,它会发回“嗨,我在这里!”的信号,然后成功地检测到它连接的端口。我用C#编写了一个任务,它等待来自硬件设备的响应,但是如果它没有连接,那么这个任务将永远等待。。我在哪里可以抛出异常来防止这种无休止的等待 我的代码: public static Task<string> GetDevicePortName() { // Get all available serial ports on system. va

我有一个硬件设备通过串行端口连接到我的电脑,当我向它发送信号时,它会发回“嗨,我在这里!”的信号,然后成功地检测到它连接的端口。我用C#编写了一个任务,它等待来自硬件设备的响应,但是如果它没有连接,那么这个任务将永远等待。。我在哪里可以抛出异常来防止这种无休止的等待

我的代码:

public static Task<string> GetDevicePortName()
{
    // Get all available serial ports on system.
    var ports = SerialPort.GetPortNames();
    var serialPort = new SerialPort();

    serialPort.BaudRate = Constants.DeviceConstants.BaudRate;
    serialPort.Parity = Constants.DeviceConstants.SerialPortParity;
    serialPort.StopBits = Constants.DeviceConstants.SerialPortStopBits;
    serialPort.WriteTimeout = Constants.DeviceConstants.WriteTimeoutInMilliseconds;

    var taskCompletionSource = new TaskCompletionSource<string>();
    serialPort.DataReceived += (s, e) => 
    {
        var dataIn = (byte)serialPort.ReadByte();
        var receivedCharacter = Convert.ToChar(dataIn);

        if (receivedCharacter == Constants.DeviceConstants.SignalYes)
        {
            serialPort.Dispose();
            taskCompletionSource.SetResult(serialPort.PortName);
        }
    };

    foreach (var port in ports)
    {
        serialPort.PortName = port;

        try
        {
            serialPort.Open();
            serialPort.Write(Constants.DeviceConstants.SignalDeviceDetect);
        }
        catch (IOException e) { }
    }

    return taskCompletionSource.Task;
}
公共静态任务GetDevicePortName()
{
//获取系统上所有可用的串行端口。
var ports=SerialPort.GetPortNames();
var serialPort=新的serialPort();
serialPort.BaudRate=常数.DeviceConstants.BaudRate;
serialPort.Parity=Constants.DeviceConstants.SerialPortParity;
serialPort.StopBits=Constants.DeviceConstants.SerialPortStopBits;
serialPort.WriteTimeout=Constants.DeviceConstants.WriteTimeOutin毫秒;
var taskCompletionSource=新的taskCompletionSource();
serialPort.DataReceived+=(s,e)=>
{
var dataIn=(字节)serialPort.ReadByte();
var receivedCharacter=Convert.ToChar(数据输入);
if(receivedCharacter==常量.DeviceConstants.SignalYes)
{
serialPort.Dispose();
taskCompletionSource.SetResult(serialPort.PortName);
}
};
foreach(端口中的var端口)
{
serialPort.PortName=端口;
尝试
{
serialPort.Open();
serialPort.Write(常量.DeviceConstants.SignalDeviceDetect);
}
捕获(IOE){}
}
返回taskCompletionSource.Task;
}
您可以将
任务与
任务相结合创建一个“自定义超时”。当任何
任务相结合时。延迟

public async Task GetDevicePortNameAsync()
{
    var cts = new CancellationTokenSource();
    var timeOutTask = Task.Delay(5000, cts.Token);
    var deviceNameTask = GetDevicePortName(cts.Token);

    var finishedTask = await Task.WhenAny(timeOut, deviceNameTask);
    if (finishedTask == timeOutTask)
    {
        // You've timed-out
    }
    // If you get here, the deviceName is available.
}
注意:这不会取消对
SerialPort
的基础注册

编辑

@KDecker增加了传递
CancellationToken
的想法,如果我们在返回
TaskCompletionSource.Task
之前已经超时,可以监视该令牌。它看起来是这样的:

public static Task<string> GetDevicePortName(CancellationToken cancellationToken)
{
    // Get all available serial ports on system.
    var ports = SerialPort.GetPortNames();
    var serialPort = new SerialPort();

    serialPort.BaudRate = Constants.DeviceConstants.BaudRate;
    serialPort.Parity = Constants.DeviceConstants.SerialPortParity;
    serialPort.StopBits = Constants.DeviceConstants.SerialPortStopBits;
    serialPort.WriteTimeout = Constants.DeviceConstants.WriteTimeoutInMilliseconds;

    var taskCompletionSource = new TaskCompletionSource<string>();
    serialPort.DataReceived += (s, e) => 
    {
        var dataIn = (byte)serialPort.ReadByte();
        var receivedCharacter = Convert.ToChar(dataIn);

        if (receivedCharacter == Constants.DeviceConstants.SignalYes)
        {
            serialPort.Dispose();
            taskCompletionSource.SetResult(serialPort.PortName);
        }
    };

    foreach (var port in ports)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            // Unregister from serialPort, and clean up whatever needs to be cleaned
            taskCompletionSource.SetResult(null);
            break;
        }

        serialPort.PortName = port;

        try
        {
            serialPort.Open();
            serialPort.Write(Constants.DeviceConstants.SignalDeviceDetect);
        }
        catch (IOException e) { }
        finally
        {
            serialPort.Dispose();
        }
    }

    return taskCompletionSource.Task;
}
公共静态任务GetDevicePortName(CancellationToken CancellationToken)
{
//获取系统上所有可用的串行端口。
var ports=SerialPort.GetPortNames();
var serialPort=新的serialPort();
serialPort.BaudRate=常数.DeviceConstants.BaudRate;
serialPort.Parity=Constants.DeviceConstants.SerialPortParity;
serialPort.StopBits=Constants.DeviceConstants.SerialPortStopBits;
serialPort.WriteTimeout=Constants.DeviceConstants.WriteTimeOutin毫秒;
var taskCompletionSource=新的taskCompletionSource();
serialPort.DataReceived+=(s,e)=>
{
var dataIn=(字节)serialPort.ReadByte();
var receivedCharacter=Convert.ToChar(数据输入);
if(receivedCharacter==常量.DeviceConstants.SignalYes)
{
serialPort.Dispose();
taskCompletionSource.SetResult(serialPort.PortName);
}
};
foreach(端口中的var端口)
{
if(cancellationToken.IsCancellationRequested)
{
//从serialPort注销,并清理需要清理的任何内容
taskCompletionSource.SetResult(空);
打破
}
serialPort.PortName=端口;
尝试
{
serialPort.Open();
serialPort.Write(常量.DeviceConstants.SignalDeviceDetect);
}
捕获(IOE){}
最后
{
serialPort.Dispose();
}
}
返回taskCompletionSource.Task;
}

这很有效。要完成此操作,请使用
TaskCancellationSource
,并在整个串行端口代码中检查该源的
CancellationToken
。如果超时,则可以调用令牌上的cancel并停止串行端口代码继续,也可以取消
任务。如果串行端口代码在它之前完成,则延迟
。@KDecker这是一个很好的注释。向实现中添加了一个可能的实现。感谢您的回答!:)如果项目与
SerialPort
进行“大量”通信,则可能对项目有用的方法是在
Ports.SerialPort
之上编写一个小型帮助器类,使用一些简单的方法,例如线程安全的
Open(config)Close(dispose)string Read()write(msg)
。然后,您可以生成
任务
以本答案中描述的方式进行竞价,可能会使代码更干净。这是个好主意,谢谢!)