Я занимаюсь разработкой программы на C #, которая связывается с позиционерами через RS232. Я хотел бы, чтобы эта программа отпустила все последовательные порты, когда она выключается и когда происходит сбой. Это не так.
Фактическая архитектура - конвертер USB в RS485. Каждый раз, когда я закрываю и снова открываю программу, она не может получить контроль над портами и ошибками. Я должен переключить USB-кабели на новые разъемы, чтобы освободить их, а именно:
System.UnauthorizedAccessException: 'Access Denied: COM6'
Это происходит в 100% случаев, если программа падает или я нажимаю на квадрат, чтобы остановитьотладки. Это происходит в 50% - 75% случаев, когда я выключаю программу отладки по порядку.
Интересно, связано ли это со средой отладки.
Чтобы попытаться это исправитьЯ создаю экземпляр класса ComPort для каждого существующего com-порта. Он реализует IDisposable и, как предполагается, освобождает свой com-порт при утилизации.
Dispose () запускается, как и ожидалось.
public class ComPort : INotifyPropertyChanged, IDisposable
{
public ComPort(string name)
{
portStream.PortName = name;
PositionerNodes.CollectionChanged += Nodes_CollectionChanged;
SetPortDefaults();
try
{
portStream.Open();
// TODO: Implement user-select on number of nodes
}
catch (UnauthorizedAccessException ex)
{
if (name == "COM1")
{
// eat the exception
}
else
{
Reporter.Warn($"Unable to get access to {name}. Another process may be using it.", $"Exception:\n\n{ex.Message}\n\n\nInner exception:\n\n {ex.InnerException?.Message ?? "No inner"}");
throw;
}
}
<snip></snip>
}
<snip></snip>
// IDisposable Support
private bool disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
foreach (Node node in Nodes)
{
node.Stop();
}
}
// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
Debug.WriteLine($"Start dispose {portStream.PortName}");
#if DEBUG
string report = $"Finish dispose {portStream.PortName}";
#endif
if (!portStream.IsDisposed)
{
if (portStream.IsOpen)
{
portStream.Close();
}
portStream.Dispose();
}
Debug.WriteLine(report);
// TODO: set large fields to null.
disposedValue = true;
}
}
// TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
~ComPort()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(false);
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
// TODO: uncomment the following line if the finalizer is overridden above.
GC.SuppressFinalize(this);
}
}
Кроме того, у меня есть метод в App.xaml.cs, которыйПредполагается, что выключение завершается при выходе и необработанных исключениях. Эти методы, похоже, запускаются, как и ожидалось.
public partial class App : Application
{
private void Application_Startup(object sender, StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
ShutDown();
}
private void Application_Exit(object sender, ExitEventArgs e)
{
ShutDown();
}
private void ShutDown()
{
foreach (Node node in ComPortManager.ComPorts.SelectMany(x => x.Nodes))
{
Debug.WriteLine($"Node: {node.ID}");
node.Stop();
}
foreach (ComPort comPort in ComPortManager.ComPorts)
{
comPort.Dispose();
}
}
}
}