Runtime: SerialPort The Requested Resource is in Use (both .net core and .net framework)

Created on 14 Jul 2019  ·  23Comments  ·  Source: dotnet/runtime

I use this code:

using System;
using System.IO.Ports;
using System.Threading.Tasks;

namespace sp
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialPort port = new SerialPort();
            port.PortName = "COM3";
            while (true)
            {
                Console.WriteLine($"port open: {port.IsOpen}");
                if (!port.IsOpen)
                {
                    foreach (var i in SerialPort.GetPortNames())
                    {
                        Console.WriteLine($"scan port {i}");
                        if (i == port.PortName)
                            try
                            {
                                port.Open();
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine($"error: {e}");
                            }
                    }
                }
                Task.Delay(1000).Wait();
            }
        }
    }
}

I run this code, connect my 4GLTE device and srart it, the code connect success

but, if I restart my 4GLTE device(not disconnect, only press restart button, this COM will disappear in Device Manager), it will show an error message: The Requested Resource is in Use, and not disappear in serial port list.

when my device is restart ok, it will still report this error, until I close my program and rerun.

this bug is also in .net framework, same code.(I tried to report this, but nobody reply me)

code logs:

port open: False
port open: False
scan port COM3
scan port COM4
scan port COM5
port open: True
port open: True
port open: True
port open: False
scan port COM3
error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in C:\Users\chenx\Desktop\sp\sp\Program.cs:line 24
port open: False
scan port COM3
error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in C:\Users\chenx\Desktop\sp\sp\Program.cs:line 24

************some same logs**************

port open: False
scan port COM3
error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in C:\Users\chenx\Desktop\sp\sp\Program.cs:line 24

************* device restart complete here **************

port open: False
scan port COM3
error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in C:\Users\chenx\Desktop\sp\sp\Program.cs:line 24
scan port COM4
scan port COM5
port open: False
scan port COM3
error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in C:\Users\chenx\Desktop\sp\sp\Program.cs:line 24
scan port COM4
scan port COM5
port open: False
scan port COM3
error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in C:\Users\chenx\Desktop\sp\sp\Program.cs:line 24
scan port COM4
scan port COM5

************same logs forever**************

more infomation:

  1. I tried many different device, only this 4GLTE device will show this problem
  2. I tried many different serial port debug tools, I found that all of tools written in C# will show this problem, other written in cpp or python are all normal
  3. Same problem in .net framework (I tested on .net framework 4.7.2 and .net core 2.1)

is this my wrong usage?

area-System.IO

Most helpful comment

@chenxuuu After you'll open the serial port, you can keep a local reference to the base stream. When you need to reconnect just dispose the local reference.

 class Program
    {
        static void Main(string[] args)
        {
            SerialPort port = new SerialPort();
            port.PortName = "COM4";

            Stream portBaseStream;

            while (true)
            {
                Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}port open: {port.IsOpen}");
                if (!port.IsOpen)
                {
                    foreach (var i in SerialPort.GetPortNames())
                    {
                        Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}scan port {i}");
                        if (i == port.PortName)
                            try
                            {
portBaseStream?.Dispose();

                                try
                                {
                                    port.BaseStream.Dispose();
                                }
                                catch(Exception ex)
                                {
                                    Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}BaseStream: {ex}");
                                }
                                port.Dispose();
                                port = new SerialPort();
                                port.PortName = "COM4";
                                port.Open();

portBaseStream = port.BaseStream;

                            }
                            catch (Exception e)
                            {
                                Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}error: {e}");
                            }
                    }
                }
                Task.Delay(1000).Wait();
            }
        }
    }

All 23 comments

sp.zip
my test project

cc: @krwq

@chenxuuu, inside of the try..catch which reopens could you replace port.Open(); with

port.Dispose();
port = new SerialPort();
port.PortName = "COM3";
port.Open();

and see if that workarounds the problem?

@krwq not work, same problem.
also, I have tried port.Dispose() and port.BreakState = false two weeks ago.

more infomation:
this device use a driver without signature, I need to disable driver signature enforcement.
when this device start complete, it will provide 3 virtual serial ports.

@chenxuuu interesting, I'd expect disposing and re-creating it to solve this. Are you sure you didn't skip port = new SerialPort(); after Dispose when you've tried it 2 weeks ago? Could you also try Disposing port.BaseStream before disposing port and see if that makes any difference?

dosen't work😕

my new code and logs:

using System;
using System.IO.Ports;
using System.Threading.Tasks;

namespace sp
{
    class Program
    {
        static void Main(string[] args)
        {
            SerialPort port = new SerialPort();
            port.PortName = "COM4";

            while (true)
            {
                Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}port open: {port.IsOpen}");
                if (!port.IsOpen)
                {
                    foreach (var i in SerialPort.GetPortNames())
                    {
                        Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}scan port {i}");
                        if (i == port.PortName)
                            try
                            {
                                try
                                {
                                    port.BaseStream.Dispose();
                                }
                                catch(Exception ex)
                                {
                                    Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}BaseStream: {ex}");
                                }
                                port.Dispose();
                                port = new SerialPort();
                                port.PortName = "COM4";
                                port.Open();
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}error: {e}");
                            }
                    }
                }
                Task.Delay(1000).Wait();
            }
        }
    }
}
[2019-07-16 10:17:42:9674]port open: False
[2019-07-16 10:17:43:0669]scan port COM4     /*************  open success  *************/
[2019-07-16 10:17:43:0965]BaseStream: System.InvalidOperationException: The BaseStream is only available when the port is open.
   at System.IO.Ports.SerialPort.get_BaseStream()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 27
[2019-07-16 10:17:43:2723]scan port COM5
[2019-07-16 10:17:43:2725]scan port COM6
[2019-07-16 10:17:44:2824]port open: True
[2019-07-16 10:17:45:2891]port open: True
[2019-07-16 10:17:46:2901]port open: True
[2019-07-16 10:17:47:2911]port open: True
[2019-07-16 10:17:48:2927]port open: True
[2019-07-16 10:17:49:2935]port open: True

/*************  I restart device here, all ports disappeared in Device Manager  *************/

[2019-07-16 10:17:50:2955]port open: False
[2019-07-16 10:17:50:2959]scan port COM4
[2019-07-16 10:17:50:3129]BaseStream: System.InvalidOperationException: The BaseStream is only available when the port is open.
   at System.IO.Ports.SerialPort.get_BaseStream()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 27
[2019-07-16 10:17:50:3619]error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 36
[2019-07-16 10:17:51:3659]port open: False
[2019-07-16 10:17:51:3663]scan port COM4
[2019-07-16 10:17:51:3822]BaseStream: System.InvalidOperationException: The BaseStream is only available when the port is open.
   at System.IO.Ports.SerialPort.get_BaseStream()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 27
[2019-07-16 10:17:51:3998]error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 36

/*************  same logs, skip  *************/

[2019-07-16 10:17:52:4069]port open: False
[2019-07-16 10:17:52:4074]scan port COM4
[2019-07-16 10:17:52:4267]BaseStream: System.InvalidOperationException: The BaseStream is only available when the port is open.
   at System.IO.Ports.SerialPort.get_BaseStream()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 27
[2019-07-16 10:17:52:4453]error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 36

/*************  device boot complete, 3 ports appeared in Device Manager  *************/

[2019-07-16 10:18:07:0075]port open: False
[2019-07-16 10:18:07:0079]scan port COM4
[2019-07-16 10:18:07:0366]BaseStream: System.InvalidOperationException: The BaseStream is only available when the port is open.
   at System.IO.Ports.SerialPort.get_BaseStream()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 27
[2019-07-16 10:18:07:0640]error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 36
[2019-07-16 10:18:07:0703]scan port COM5
[2019-07-16 10:18:07:0720]scan port COM6
[2019-07-16 10:18:08:0747]port open: False
[2019-07-16 10:18:08:0755]scan port COM4
[2019-07-16 10:18:08:1209]BaseStream: System.InvalidOperationException: The BaseStream is only available when the port is open.
   at System.IO.Ports.SerialPort.get_BaseStream()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 27
[2019-07-16 10:18:08:1468]error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 36
[2019-07-16 10:18:08:1537]scan port COM5
[2019-07-16 10:18:08:1568]scan port COM6

/*************  same logs, skip  *************/

[2019-07-16 10:18:14:3647]port open: False
[2019-07-16 10:18:14:3652]scan port COM4
[2019-07-16 10:18:14:3826]BaseStream: System.InvalidOperationException: The BaseStream is only available when the port is open.
   at System.IO.Ports.SerialPort.get_BaseStream()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 27
[2019-07-16 10:18:14:3988]error: System.IO.IOException: 请求的资源在使用中。
   at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
   at System.IO.Ports.SerialStream..ctor(String portName, Int32 baudRate, Parity parity, Int32 dataBits, StopBits stopBits, Int32 readTimeout, Int32 writeTimeout, Handshake handshake, Boolean dtrEnable, Boolean rtsEnable, Boolean discardNull, Byte parityReplace)
   at System.IO.Ports.SerialPort.Open()
   at sp.Program.Main(String[] args) in D:\OneDrive\同步文件夹\luat_desktop\sp\sp\Program.cs:line 36
[2019-07-16 10:18:14:4014]scan port COM5
[2019-07-16 10:18:14:4019]scan port COM6

C:\Program Files\dotnet\dotnet.exe (进程 11744)已退出,返回代码为: -1。
若要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口...

need I mail a device for testing?

@chenxuuu, I don't think that will be necessary

need I do some other tests?

@chenxuuu what kind of serial port are you using? (i.e. usb/uart/physical com port). It would be interesting to inspect the process with i.e. Process Explorer and see what kind of file handles are open while this is happening - we are very likely not disposing something in the code.

@krwq A 4G module,with 3 serial ports from 1 usb.
I record a screen video: https://1drv.ms/v/s!Asz6jM0Kmex1p8wRA1P9Fakx9qvOvw?e=DV2fRt

any solution?

@chenxuuu unfortunately I'm unable to reproduce this. I've run the repro re-plugged my device several times and works as expected.

I think this might be an issue with your device (or driver). Perhaps the driver reports it too quickly as available...

One thing you can try is to perhaps when opening a port fails add some delay and retry couple of times before declaring it failed - this is not fixing the problem but at least might workaround it.

can't reopen those port, Dispose is useless, unless restart program.

my 4g module is based on ASR1802s(Air720).
this bug also happends on my another 4g module based on Qualcomm MDM9207(U9300C).

all device work's well with c/cpp codes.
all tools wroten by c# have this problem (I find them on internet, not wroten by me).

@chenxuuu could you share the C/C++ code you are using and works for you for reference? Also could you point me to somewhere where I can get the specific device you're seeing the problem with? (i.e. amazon/aliexpress link).

Also what version of System.IO.Ports package are you using?

my cpp code:

// ConsoleApplication1.cpp
//

#include <iostream>
#include <windows.h>
using namespace std;
HANDLE hMutex;

DWORD WINAPI Read(LPVOID lpParamter)
{
    while (1)
    {
        //open port
        HANDLE hCom = CreateFileA("com4", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, 0);
        //set timeout
        COMMTIMEOUTS timeouts;
        GetCommTimeouts(hCom, &timeouts);
        timeouts.ReadIntervalTimeout = 0;
        timeouts.ReadTotalTimeoutMultiplier = 0;
        timeouts.ReadTotalTimeoutConstant = 1;
        timeouts.WriteTotalTimeoutMultiplier = 0;
        timeouts.WriteTotalTimeoutConstant = 0;
        if (!SetCommTimeouts(hCom, &timeouts))
        {
            cout << "timeout" << endl;
            CloseHandle(hCom);
            Sleep(5000);
            continue;
        }

        //get port state
        DCB dcb;
        GetCommState(hCom, &dcb);
        dcb.DCBlength = sizeof(DCB);
        dcb.BaudRate = 9600;
        dcb.Parity = 0;
        dcb.ByteSize = 8;
        dcb.StopBits = ONESTOPBIT;
        if (!SetCommState(hCom, &dcb))
        {
            cout << "open fail" << endl;
            CloseHandle(hCom);
            Sleep(5000);
            continue;
        }

        cout << "open success" << endl;

        char buffer[1024];
        DWORD readsize, dwError;
        BOOL bReadStatus;
        COMSTAT cs;

        WaitForSingleObject(hMutex, INFINITE);
        while (1)
        {
            readsize = 0;
            ClearCommError(hCom, &dwError, &cs);//get port state
            if (dwError != 0)
            {
                cout << "uart error: " << dwError << endl;
                break;
            }
            Sleep(5);
        }
        ReleaseMutex(hMutex);
        CloseHandle(hCom);
        cout << "uart closed" << endl;
        Sleep(1000);
    }
}

void main(void)
{
    HANDLE hThread = CreateThread(NULL, 0, Read, NULL, 0, NULL);
    hMutex = CreateMutex(NULL, FALSE, NULL);
    CloseHandle(hThread);
    while (1)
        Sleep(1000);
}

outpot:

open success
uart error: 31      <====I restart my device here
uart closed
timeout
timeout
timeout
timeout
open success    <====device boot complete

Air720 board can be found on aliexpress and taobao
https://www.aliexpress.com/item/4000097129001.html
https://item.taobao.com/item.htm?id=588424557201


I tested c# codes with vs2019's default .net core 2.1 and .net framework 4.7.2

any progress?
I want to test this c# code on linux, maybe not same as windows

@chenxuuu unfortunately I haven't had time to take a look at this yet. To make progress here it might be worth if you can find the diff between your C++ code vs what we do in our implementation and we can decide what to do from there.

Also as you mentioned you might want to check the Linux since the code is different enough the issue might not be present there (if that is an acceptable workaround for you).

Triage:
@chenxuuu did you get a chance to check the diff @krwq mentioned? https://github.com/dotnet/runtime/issues/30251#issuecomment-550547924

@carlossanlop I have no linux envernmrnt now, and maybe WSL can't check this. I will try to find a ubuntu machine to test it

@chenxuuu After you'll open the serial port, you can keep a local reference to the base stream. When you need to reconnect just dispose the local reference.

 class Program
    {
        static void Main(string[] args)
        {
            SerialPort port = new SerialPort();
            port.PortName = "COM4";

            Stream portBaseStream;

            while (true)
            {
                Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}port open: {port.IsOpen}");
                if (!port.IsOpen)
                {
                    foreach (var i in SerialPort.GetPortNames())
                    {
                        Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}scan port {i}");
                        if (i == port.PortName)
                            try
                            {
portBaseStream?.Dispose();

                                try
                                {
                                    port.BaseStream.Dispose();
                                }
                                catch(Exception ex)
                                {
                                    Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}BaseStream: {ex}");
                                }
                                port.Dispose();
                                port = new SerialPort();
                                port.PortName = "COM4";
                                port.Open();

portBaseStream = port.BaseStream;

                            }
                            catch (Exception e)
                            {
                                Console.WriteLine($"{DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss:ffff]")}error: {e}");
                            }
                    }
                }
                Task.Delay(1000).Wait();
            }
        }
    }

@zapadi thanks! this code works fine

Thank you @zapadi for your help!
@chenxuuu I will close this issue as it seems to be resolved with that suggestion. Feel free to reopen if you have additional questions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

noahfalk picture noahfalk  ·  3Comments

matty-hall picture matty-hall  ·  3Comments

aggieben picture aggieben  ·  3Comments

GitAntoinee picture GitAntoinee  ·  3Comments

jchannon picture jchannon  ·  3Comments