主程序需要动态加载一个dll,该dl初始化时启动了一个UdpClient,主程序退出时【长】……

wzuomin 2008-04-18 04:45:41
主程序需要动态加载一个dll,该dl初始化时启动了一个UdpClient,打开并监视一个端口
在主程序关闭退出后,再启动的话会提示错误: 通常每个套接字地址 (协议/网络地址/端口) 只允许使用一次
分析造成这个问题的原因是:主程序退出时动态加载的dll没有释放该端口

这个问题该怎么解决啊?
...全文
264 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
天明啊 2011-03-24
  • 打赏
  • 举报
回复
wzuomin 2008-05-06
  • 打赏
  • 举报
回复
这个问题真是头疼啊!没有好的解决方法吗?
谢谢大家,但是仍没有完美的解决呐!
q979851 2008-05-06
  • 打赏
  • 举报
回复
有时候程序窗体关了,但任务栏上的进程没关,
所以造成端口没关,
感觉winform没点不稳定
fox1999 2008-04-21
  • 打赏
  • 举报
回复
UDP 有時會這樣,你打開一個端口,關閉後,馬上再打開,會提示端口已被占用
wzuomin 2008-04-20
  • 打赏
  • 举报
回复
希望有人继续关注!
wzuomin 2008-04-19
  • 打赏
  • 举报
回复
自动转换的C#代码如下:不能保证能正常运行,呵呵
主程序代码:

using System.Reflection;

public class Form1
{

private System.Windows.Forms.ToolStrip TestToolStrip;

private void Form1_Load(object sender, System.EventArgs e)
{
this.TestToolStrip = new ToolStrip();
this.TestToolStrip.Items.Add(new ToolStripButton("TestButton"));
this.TestToolStrip.Items.Add(new ToolStripComboBox("TestComboBox"));
this.TestToolStrip.Items.Add(new ToolStripDropDownButton("TestDropDownButton"));
this.TestToolStrip.Dock = DockStyle.Top;
this.Controls.Add(this.TestToolStrip);

string Path = Application.StartupPath + "\\Extended";
string FileName = FileSystem.Dir(Path + "\\*.dll");

while (FileName != "") {
AddExtendItem(Path + "\\" + FileName);
FileName = FileSystem.Dir();
}
}

private void AddExtendItem(string dllFilePath)
{
try {
Assembly a = Assembly.LoadFrom(dllFilePath);
Type[] MyTypes = a.GetTypes();

foreach (Type t in MyTypes) {
if (t.Name == "ExtendedItem") {
object[] Parameters = {this.TestToolStrip};
object obj = Activator.CreateInstance(t, Parameters);
break; // TODO: might not be correct. Was : Exit For
}
}
}
catch (Exception ex) {
Interaction.MsgBox(ex.Message, MsgBoxStyle.Critical, "Error");
}
}

}


测试用的dll代码如下:

using System.Windows.Forms;

public class ExtendedItem
{

ToolStripDropDownButton Testbtn;
private Threading.Thread ListenThread;
private Net.Sockets.UdpClient listen;

public ExtendedItem(ToolStrip _ToolStrip)
{
this.Testbtn = new ToolStripDropDownButton("TestDllDropDownButton");
{
this.Testbtn.DropDownItems.Add("TestItem1");
this.Testbtn.DropDownItems.Add("TestItem2");
this.Testbtn.DropDownItems.Add("CloseUdpClient", null, Close);
}
_ToolStrip.Items.Add(this.Testbtn);

try {
listen = new Net.Sockets.UdpClient(2525);
ListenThread = new Threading.Thread(ListenPort);
ListenThread.Start();
}
catch (Exception ex) {
Interaction.MsgBox(ex.Message, MsgBoxStyle.Critical, "Error");
}
}

//侦听指定端口的广播地址UDP包
private void ListenPort()
{
Net.IPEndPoint tempEnd = new Net.IPEndPoint(Net.IPAddress.Any, 2525);
while (true) {
Application.DoEvents();
try {
byte[] recb = listen.Receive(tempEnd);
CheckMessage(recb);
}
catch (Exception e) {
break; // TODO: might not be correct. Was : Exit Try
}
}
}

private void CheckMessage(byte[] bytes)
{
//省略
}

private void Close(object sender, System.EventArgs e)
{
if (ListenThread != null)
ListenThread.Abort();
if (listen != null)
listen.Close();
}

}
wzuomin 2008-04-19
  • 打赏
  • 举报
回复
举个例子说明一下吧
比如我有个主程序,在Load的时候会在某个指定目录中查找是否有dll需要加载
代码如下:

Imports System.Reflection

Public Class Form1

Private TestToolStrip As System.Windows.Forms.ToolStrip

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Me.TestToolStrip = New ToolStrip
Me.TestToolStrip.Items.Add(New ToolStripButton("TestButton"))
Me.TestToolStrip.Items.Add(New ToolStripComboBox("TestComboBox"))
Me.TestToolStrip.Items.Add(New ToolStripDropDownButton("TestDropDownButton"))
Me.TestToolStrip.Dock = DockStyle.Top
Me.Controls.Add(Me.TestToolStrip)

Dim Path As String = Application.StartupPath + "\Extended"
Dim FileName As String = Dir(Path + "\*.dll")

While FileName <> ""
Call AddExtendItem(Path + "\" + FileName)
FileName = Dir()
End While
End Sub

Private Sub AddExtendItem(ByVal dllFilePath As String)
Try
Dim a As [Assembly] = [Assembly].LoadFrom(dllFilePath)
Dim MyTypes As Type() = a.GetTypes()

For Each t As Type In MyTypes
If t.Name = "ExtendedItem" Then
Dim Parameters() As Object = {Me.TestToolStrip}
Dim obj As [Object] = Activator.CreateInstance(t, Parameters)
Exit For
End If
Next
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Error")
End Try
End Sub

End Class



我编写了一个测试用的dll,代码如下:

Imports System.Windows.Forms

Public Class ExtendedItem

Dim Testbtn As ToolStripDropDownButton
Private ListenThread As Threading.Thread
Private listen As Net.Sockets.UdpClient

Public Sub New(ByVal _ToolStrip As ToolStrip)
Me.Testbtn = New ToolStripDropDownButton("TestDllDropDownButton")
With Me.Testbtn.DropDownItems
.Add("TestItem1")
.Add("TestItem2")
.Add("CloseUdpClient", Nothing, AddressOf Close)
End With
_ToolStrip.Items.Add(Me.Testbtn)

Try
listen = New Net.Sockets.UdpClient(2525)
ListenThread = New Threading.Thread(AddressOf ListenPort)
ListenThread.Start()
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, "Error")
End Try
End Sub

'侦听指定端口的广播地址UDP包
Private Sub ListenPort()
Dim tempEnd As New Net.IPEndPoint(Net.IPAddress.Any, 2525)
While True
Application.DoEvents()
Try
Dim recb As Byte() = listen.Receive(tempEnd)
Call CheckMessage(recb)
Catch e As Exception
Exit Try
End Try
End While
End Sub

Private Sub CheckMessage(ByVal bytes() As Byte)
'省略
End Sub

Private Sub Close(ByVal sender As Object, ByVal e As System.EventArgs)
If ListenThread IsNot Nothing Then ListenThread.Abort()
If listen IsNot Nothing Then listen.Close()
End Sub

End Class



这样,程序运行后,在主程序的 ToolStrip 中会增加一个DropDownButton(该Button带有数个下拉菜单项)。
如果先执行这个button的下拉菜单 CloseUdpClient,再关闭主程序,下次启动不会有任何问题。
但是如果直接关闭主程序,就不行了,下次启动肯定会报错的。
就是这么个情况,麻烦大家给出出主意吧!呵呵。
一会儿把自动转换的C#代码我也贴过来,帮忙看看吧。先谢谢了!
ycg_893 2008-04-19
  • 打赏
  • 举报
回复
UdpClient与主程不是同一线程,当主程退出后,UdpClient还在占用端口并在进程中,所以可以让主程序退出时,终止UdpClient进程.
minioreo 2008-04-19
  • 打赏
  • 举报
回复
mark
yunfeng007 2008-04-19
  • 打赏
  • 举报
回复
??dll不是自己的,那就自己做个Wrapper类来做包装,然后在此做清理的工作
yunfeng007 2008-04-19
  • 打赏
  • 举报
回复

internal class UdpClient
{
public UdpClient(){}//初始化,构造函数
~UdpClient(){}//显示声明析构函数,在此做清理工作
}

possible_Y 2008-04-19
  • 打赏
  • 举报
回复
那是那个动态dll的问题了,让dll的作者自己去改,让他记得做非托管资源的释放
wzuomin 2008-04-19
  • 打赏
  • 举报
回复
楼上说的确实不错,可是动态加载的dll主程序该如何管理或者调用stop方法呢?
我现在就是苦于没法调用动态加载的dll里的方法啊!
shrinerain 2008-04-19
  • 打赏
  • 举报
回复
你需要显式给DLL设计一个清理函数.

由DLL申请的资源, 需要DLL自己来释放.

对于这个DLL, 你可以设计一个初始化函数, 和一个清理函数.

比如, 你给DLL设计一个Start()函数, 负责申请Socket资源, 还有一个Stop()函数,负责撤销Socket资源.

在你EXE调用中, 显式使用Start()来运行DLL, 并且在程序退出事件时, 调用Stop()来让DLL清理资源.
wzuomin 2008-04-19
  • 打赏
  • 举报
回复
UdpClient 只是在一个dll中运行的呀!是动态加载运行的,怎么终止啊?
wzuomin 2008-04-19
  • 打赏
  • 举报
回复
大家提供的方法不知道你们试过没有?说的方法实际上可行么?

我在vb中的Finalize中增加了调用Close方法,还是不行。

还有18楼说的在FormClosing中关闭,怎么个关闭方法啊?

如果我不是动态加载,在主程序中增加 Private Test As TestDll.ExtendedItem
,然后Form Load的时候 Test = New TestDll.ExtendedItem(Me.TestToolStrip)
这样子的话可以用下面方法解决这个问题
Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Test.Close(Nothing, Nothing)
End Sub
wanghui0380 2008-04-19
  • 打赏
  • 举报
回复
??不是很复杂的问题啊
socket开启了监听端口,但退出的时候,没有关闭监听端口。问题就是如此啊,没啥思维上的障碍嘛

在FormClosing事件里关闭就可以了

如果是自己的dll,也可以加析构函数嘛

yunfeng007 2008-04-19
  • 打赏
  • 举报
回复

using System.Windows.Forms;

public class ExtendedItem
{
//将dll修改,增加析构函数。不行吗?
~ExtendedItem()
{
Close(null,null);
}

private void Close(object sender, System.EventArgs e)
{
if (ListenThread != null)
ListenThread.Abort();
if (listen != null)
listen.Close();
}
}

主线程关闭,dll肯定被释放了,但因为socket没有主动close,端口依然被占用
wzuomin 2008-04-18
  • 打赏
  • 举报
回复
Application.Exit这句加了也不行。
duping9626 2008-04-18
  • 打赏
  • 举报
回复
主程序退出时
Application.Exit()试试呢
加载更多回复(4)
内容概要:本文档是关于“基于小信号扫频辨识的光伏并网逆变器正负序交互稳定性分析”的博士论文复现资源,配套提供Matlab代码与Simulink仿真实现。内容聚焦于弱电网条件下光伏并网逆变器的稳定性问题,深入研究其正负序阻抗建模方法、小信号扫频辨识技术及正负序交互失稳机理。通过构建高精度的系统仿真模型,采用扫频法提取逆变器在不同控制环路(如锁相环、电流环)影响下的序阻抗特性,并结合奈奎斯特稳定性判据评估其与电网阻抗之间的交互作用,系统性地揭示了宽频带振荡的产生机制。该资源完整还原了论文中的关键理论推导与仿真验证流程,适用于从事新能源并网、电力电子系统建模与稳定性分析的研究人员进行学习、复现与二次开发。; 适合人群:具备电力系统、电力电子与自动控制理论基础,熟练掌握Matlab/Simulink仿真工具,从事新能源发电并网、逆变器控制策略或电力系统稳定性研究的研究生、科研人员及工程技术人员。; 使用场景及目标:① 复现并验证博士论文中提出的光伏逆变器正负序阻抗建模与小信号扫频分析方法;② 深入理解弱电网环境下由正负序耦合引发的交互失稳现象及其物理机理;③ 掌握基于阻抗法的并网系统稳定性分析流程,为虚拟同步机、构网型控制等先进控制策略的稳定性研究提供技术参考与仿真支撑。; 阅读建议:建议学习者结合提供的代码与仿真模型,首先深入理解序阻抗建模与扫频辨识的基本原理,然后逐步调试仿真程序,重点关注锁相环动态、电流控制器参数对序阻抗曲线的影响,最终掌握从模型搭建、扫频测试到稳定性判据应用的全流程分析能力。

111,129

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧