我不知道如何处理 SocketException 以满足我的需要
Posted
技术标签:
【中文标题】我不知道如何处理 SocketException 以满足我的需要【英文标题】:I do not know how to handle SocketException to suit my needs 【发布时间】:2015-03-21 04:40:05 【问题描述】:简介及相关资料:
我是一名缺乏经验的 C# 开发人员,继承了同事的项目并负责修复某些错误。
其中一项任务是在 Internet 连接不可用时将应用程序切换到离线模式。我的同事使用OpenNetCF library 帮助他处理应用程序的 FTP 连接部分,这让我的工作变得更加困难。
问题在于“登录”形式。这是用户看到的第一件事,这个表单会自动尝试连接到服务器。如果没有可用的连接,它只是处于空闲状态,显示消息“正在连接...”。
问题:
如果连接不可用,我的任务是切换到离线模式。
我为解决这个问题所做的努力:
为了进一步解释,我觉得最好为登录表单的onLoad
事件提供代码:
// class fields:
delegate void StringDelegate(string value);
private FTP m_ftp;
private void dlgLoading_Load(object sender, EventArgs e)
m_ftp = new FTP(address);
m_ftp.ResponseReceived += new
FTPResponseHandler(m_ftp_ResponseReceived);
// m_ftp_Connected processes files in a certain way
m_ftp.Connected += new FTPConnectedHandler(m_ftp_Connected);
m_ftp.BeginConnect(username, password);
// sets label's text to inform the user it is connecting
lblText.Text += "Connecting... ";
通过代码调试,我发现在另一个似乎属于OpenNETCF
库的文件中抛出了异常SocketException
。它的名字是FTP.cs
,函数ConnectThread
在尝试连接时会抛出它。 ConnectThread
在上述代码中被m_ftp.BeginConnect
调用。
这很好,因为我没有调整模拟器来连接互联网。
在 JAVA 中,函数可以抛出异常。
通过阅读 C# 书籍/教程,在 Internet 和这里搜索,我发现这在 C# 中是做不到的。
但是,通过进一步搜索,我了解到在 C# 异常中未处理时会“冒泡”。
我得出的结论是,这可能是基于this 线程的良好编程实践(如果您无法处理异常,则“冒泡”异常)。
因此,我决定将异常从库中的方法一直“冒泡”到我的登录表单中的代码。然后我可以抓住它,并从那里以离线模式继续。
我已经从库/我的代码中的相关方法中删除了try/catch
块,并将上面的代码更改为:
// class fields:
delegate void StringDelegate(string value);
private FTP m_ftp;
private void dlgLoading_Load(object sender, EventArgs e)
try
m_ftp = new FTP(address);
m_ftp.ResponseReceived += new
FTPResponseHandler(m_ftp_ResponseReceived);
// m_ftp_Connected processes files in a certain way
m_ftp.Connected += new FTPConnectedHandler(m_ftp_Connected);
m_ftp.BeginConnect(username, password);
// sets label's text to inform the user it is connecting
lblText.Text += "Connecting... ";
catch( Exception ex )
MessageBox.Show( ex.Message );
// i thought of adding a check at this place
// if exception is SocketException
// so I can launch "offline code" here
我希望在那里捕获异常,但我的程序终止了。我不确定,但这让我认为异常不会在任何地方得到处理。
问题:
在这种情况下,如何正确“冒泡”这种类型的异常? 我的方法有效吗(我提醒您我非常缺乏经验)?有比我的方法更好的解决方案吗?由于缺乏经验,如果我遗漏了重要信息,我深表歉意。请发表评论,我会尽快编辑我的帖子。
【问题讨论】:
你可以有多个 catch 块。所以尝试catch(SocketException)//处理套接字错误catch(Exception)\\处理其他错误 @zaf:我可能是错的,但是在网上搜索后,我发现m_ftp.BeginConnect(username, password);
调用启动了单独的线程。正是在这个线程中发生了异常。遗憾的是,按照您的指示修改代码并没有改变任何事情。似乎在删除 try/catch
块后,异常在线程中冒泡,从未到达我的表单,从而终止了应用程序。再说一次,我可能错了,我很缺乏经验,但这是我的逻辑......
对不起,我错过了 BeginXXX 部分。无论如何,我不熟悉您正在使用的库,但通常使用 BeginXXX 的 .net 异步方法具有异步回调参数。在此回调中,您可以尝试并捕获错误。尝试查看您正在使用的 BeginConnect 方法是否过载。要将异常“冒泡”到 UI 线程,您可以使用 SynchronizationContext。
@zaf:我不熟悉你正在使用的库我也不熟悉,它是由我继承该项目的同事使用的 :) 通常使用 BeginXXX 的 .net 异步方法有一个异步回调参数。在此回调中,您可以尝试并捕获错误。尝试查看您正在使用的 BeginConnect 方法是否过载。要将异常“冒泡”到 UI 线程,您可以使用 SynchronizationContext。 目前有很多有用的信息需要处理,我将在线搜索,看看会发生什么。感谢您为我指明正确的方向。
【参考方案1】:
异步风格的方法(例如 BeginXxx)只能在回调/事件中报告错误,因为错误仅在调用返回后发生。处理回调中的错误。它将被 EndXxx 方法抛出。
对于每个 BeginXxx 调用,必须有一个对应的 EndXxx 调用,通常在回调中进行。
这是 APM 模式。
【讨论】:
感谢您的回答,非常感谢。作为这一切的新手,在我正式接受您的回答之前,我可能需要一些时间来实施您的解决方案,所以请耐心等待。最好的问候。 如果您想要一个更简单的模型,如果您的库支持,请使用 await。这是迄今为止结合 UI 运行异步工作的最简单方法。没有等待就不要使用异步 IO。使用 Task.Run 启动一个任务,它会完成所有工作。不再需要事件或回调。以上是关于我不知道如何处理 SocketException 以满足我的需要的主要内容,如果未能解决你的问题,请参考以下文章