在MS Exam 70-536 .Net Foundation中,第7章“线程”第1课“创建线程”中有一个文本:
请注意,因为WorkWithParameter方法接受一个对象Thread.Start 可以用任何对象而不是它期望的字符串调用。小心选择 你处理未知类型的线程的起始方法对于良好是至关重要的 线程代码。它不是盲目地将方法参数转换为我们的字符串 测试对象类型的更好方法,如以下示例所示:
' VB
Dim info As String = o as String
If info Is Nothing Then
Throw InvalidProgramException("Parameter for thread must be a string")
End If
// C#
string info = o as string;
if (info == null)
{
throw InvalidProgramException("Parameter for thread must be a string");
}
所以,我试过这个,但异常处理得不好(没有控制台异常输入,程序终止),我的代码有什么问题(如下)?
class Program
{
static void Main(string[] args)
{
Thread thread = new Thread(SomeWork);
try
{
thread.Start(null);
thread.Join();
}
catch (InvalidProgramException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.ReadKey();
}
}
private static void SomeWork(Object o)
{
String value = (String)o;
if (value == null)
{
throw new InvalidProgramException("Parameter for "+
"thread must be a string");
}
}
}
谢谢你的时间!
答案 0 :(得分:7)
Main
方法中的异常处理程序运行在与抛出异常不同的线程中。因此,thread
中的异常无法在Main
中捕获。检查here,了解您不希望跨线程抛出/捕获异常的原因。你应该做的是使用一个对象,它将包装你的线程逻辑但支持异常。 E.g:
class Program
{
static void Main(string[] args)
{
ExceptionHandlingThreadWrapper wrapper = new ExceptionHandlingThreadWrapper();
Thread thread = new Thread(wrapper.Run);
try
{
thread.Start(null);
thread.Join();
if (wrapper.Exception != null)
throw new Exception("Caught exception", wrapper.Exception);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally { Console.ReadKey(); }
}
}
public class ExceptionHandlingThreadWrapper
{
public ExceptionHandlingThreadWrapper()
{
this.Exception = null;
}
public Exception Exception { get; set; }
public void Run(Object obj)
{
try
{
String value = obj as String;
if (value == null)
throw new Exception("Argument must be string");
}
catch (Exception ex)
{
this.Exception = ex;
}
}
}
答案 1 :(得分:3)
首先在调试模式下启动VS.现在编写代码,有几个问题:
catch (InvalidProgramException ex)
{
Console.WriteLine(ex.Message);
}
永远不会执行因为异常是线程的本地。如果在生成的线程中抛出异常,其他线程将无法看到它。
throw new InvalidProgramException("Parameter for "+
"thread must be a string");
此行导致未处理的异常,因为在该线程中没有人捕获它。未处理的异常使整个应用程序失败。
String value = (String)o;
if (value == null)
o可以为null,这是String的有效值,如果o不是字符串,则代码将抛出异常。你的意思是:
String value = o as String;
if (value == null)
答案 2 :(得分:1)
异常不会遍历线程,它只是关闭执行代码。换句话说,您永远不会捕获在单独线程上抛出的异常。
答案 3 :(得分:1)
后台线程上的未处理异常将终止您的应用程序。这是.NET 2.0中的行为变化。如果您不希望应用程序在发生这种情况时死亡,则应将代码包装在try catch
中并记录该异常:
private static void SomeWork(Object o)
{
try
{
// execution here
}
catch (Exception ex)
{
Logger.Log(ex);
}
}
答案 4 :(得分:0)
您是否考虑过使用BeginInvoke和EndInvoke而不是创建自己的Thread?这将允许捕获异常并将其带回调用方法。
class Program
{
private delegate void WorkDelegate(Object o);
static void Main(string[] args)
{
WorkDelegate workDel = new WorkDelegate(SomeWork);
// first argument is passing a null object that will throw
// the exception in the SomeWork method
IAsyncResult result = workDel.BeginInvoke(null, null, null);
try
{
workDel.EndInvoke(result);
}
catch (InvalidProgramException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
Console.ReadKey();
}
}
private static void SomeWork(Object o)
{
String value = o as String;
if (value == null)
{
throw new InvalidProgramException("Parameter for "+
"thread must be a string");
}
}
}