我很困惑处置.我正在尝试让我的代码正确处理资源.所以我一直在将我的类设置为IDisposable(使用Dispose方法),确保调用Dispose方法.
但是现在FXCop告诉我很多关于Disposing = false和调用Dispose(false)的东西.
我没有看到一个带有bool的Dispose方法.我需要制作一个吗?如果是这样,为什么?为什么不在处理时调用一个方法呢?
我在这里看到了一些代码:http://msdn.microsoft.com/en-us/library/ms244737.aspx,它展示了如何制作一个带有bool的Disposing方法.它表示它适用于本地和管理资源. 但我认为处理的全部内容仅适用于非管理资源.
此外,FXCop抱怨的路线是这样的:
~OwnerDrawnPanel()
{
_font.Dispose();
}
Run Code Online (Sandbox Code Playgroud)
它说:
CA1063:Microsoft.Design:修改'OwnerDrawnPanel .~ OwnerDrawnPanel()',以便它调用Dispose(false)然后返回.
但是Font上没有Dispose(bool)(我能找到).
为什么我需要Dispose(bool)?如果我这样做,为什么Font没有呢?因为它没有它,为什么FXCop要求我使用它?
感谢所有的好答案.我想我现在明白了.这是
处置"非管理"资源分为两类:
Dispose(bool)用于表示两者之间的区别:
考虑将传入的SOAP请求记录到ASP.NET ASMX Web服务的要求.任务是捕获发送到Web服务的原始XML.
需要记录传入消息以进行调试检查.该应用程序已经有自己的日志库,因此理想的用法是这样的:
//string or XML, it doesn't matter.
string incomingSoapRequest = GetSoapRequest();
Logger.LogMessage(incomingSoapRequest);
Run Code Online (Sandbox Code Playgroud)
我注意到using我的代码中嵌套语句的级别最近有所增加.究其原因,可能是因为我使用越来越多的async/await格局,这往往增加了至少一个以上using的CancellationTokenSource或CancellationTokenRegistration.
那么,如何减少嵌套using,所以代码看起来不像圣诞树?之前已经提出了类似的问题,我想总结一下我从答案中学到的东西.
using而不缩进.一个假的例子:using (var a = new FileStream())
using (var b = new MemoryStream())
using (var c = new CancellationTokenSource())
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
这可能有用,但通常会有一些代码using(例如,创建另一个对象可能为时过早):
// ...
using (var a = new FileStream())
{
// ...
using (var b = new MemoryStream())
{
// ...
using (var c = new CancellationTokenSource())
{
// ...
}
}
}
Run Code Online (Sandbox Code Playgroud)
IDisposable)的对象组合成单个对象using,例如:// …Run Code Online (Sandbox Code Playgroud) 最近,我正在研究一些关于没有处理的对象的棘手错误.
我在代码中找到了一些模式.据报道,有些m_foo没有被处理,而似乎SomeClass的所有实例都被处理掉了.
public class SomeClass: IDisposable
{
void Dispose()
{
if (m_foo != null)
{
m_foo.Dispose();
}
if (m_bar != null)
{
m_bar.Dispose();
}
}
private Foo m_foo;
private Bar m_bar;
}
Run Code Online (Sandbox Code Playgroud)
我怀疑Foo.Dispose可能会抛出异常,因此不会执行以下代码,因此不会释放m_bar.
由于Foo/Bar可能来自第三方,因此不保证不会抛出异常.
如果只使用try-catch包装所有Dispose调用,代码将变得笨拙.
处理这个问题的最佳做法是什么?
显然,使用嵌套using语句时可能会丢失一些异常.考虑这个简单的控制台应用
using System;
namespace ConsoleApplication
{
public class Throwing: IDisposable
{
int n;
public Throwing(int n)
{
this.n = n;
}
public void Dispose()
{
var e = new ApplicationException(String.Format("Throwing({0})", this.n));
Console.WriteLine("Throw: {0}", e.Message);
throw e;
}
}
class Program
{
static void DoWork()
{
// ...
using (var a = new Throwing(1))
{
// ...
using (var b = new Throwing(2))
{
// ...
using (var c = new Throwing(3))
{
// ...
}
}
}
} …Run Code Online (Sandbox Code Playgroud) 通常我会遇到这样的情况:我必须吞下catch/ finallyblock中清理代码抛出的异常,以防止吞噬原始异常.
例如:
// Closing a file in Java
public void example1() throws IOException {
boolean exceptionThrown = false;
FileWriter out = new FileWriter(“test.txt”);
try {
out.write(“example”);
} catch (IOException ex) {
exceptionThrown = true;
throw ex;
} finally {
try {
out.close();
} catch (IOException ex) {
if (!exceptionThrown) throw ex;
// Else, swallow the exception thrown by the close() method
// to prevent the original being swallowed.
}
}
}
// Rolling back a transaction …Run Code Online (Sandbox Code Playgroud) 我有
void foo1()
{
using(...){...}
}
void foo2()
{
using(...){...}
}
void foo3()
{
using(...){...}
}
Run Code Online (Sandbox Code Playgroud)
我有
void foo()
{
...
backgroundWorker.DoWork += (s, ev) =>
{
try
{
foo1();
foo2();
foo3();
}
catch (Exception ex)
{
// log ex
}
};
...
}
Run Code Online (Sandbox Code Playgroud)
我只是读到了using块吞下异常.它有一种优雅的方式来处理从异常foo1(),foo2()并 foo3()在foo().我不想using在方法中的每个块内部使用try/catch .我确实偶然发现了这篇文章,建议使用扩展方法,但我只是检查是否有更好的方法.
仅供参考,网络断开导致using块内的逻辑抛出异常,这就是我在一个常见的地方尝试处理的问题.
谢谢,
在切换到新的.NET Core 3的过程中IAsynsDisposable,我偶然发现了以下问题。
问题的核心:如果DisposeAsync引发异常,则此异常隐藏await using-block 内部引发的所有异常。
class Program
{
static async Task Main()
{
try
{
await using (var d = new D())
{
throw new ArgumentException("I'm inside using");
}
}
catch (Exception e)
{
Console.WriteLine(e.Message); // prints I'm inside dispose
}
}
}
class D : IAsyncDisposable
{
public async ValueTask DisposeAsync()
{
await Task.Delay(1);
throw new Exception("I'm inside dispose");
}
}
Run Code Online (Sandbox Code Playgroud)
被捕获的是AsyncDispose-exception(如果引发了),而内部异常await using只有在AsyncDispose未引发的情况下才被捕获。
但是,我还是更喜欢它:await using …
我想将异步操作委托转换为返回指定值的异步函数委托.我想出了一个扩展方法:
public static Func<Task<TResult>> Return<TResult>(this Func<Task> asyncAction, TResult result)
{
ArgumentValidate.NotNull(asyncAction, nameof(asyncAction));
return async () =>
{
await asyncAction();
return result;
};
}
Run Code Online (Sandbox Code Playgroud)
但是,我的扩展方法是错误的,因为从操作委托同步传递的异常现在从函数委托异步传递.具体来说:
Func<Task> asyncAction = () => { throw new InvalidOperationException(); };
var asyncFunc = asyncAction.Return(42);
var task = asyncFunc(); // exception should be thrown here
await task; // but instead gets thrown here
Run Code Online (Sandbox Code Playgroud)
有没有办法以同步异常继续同步传递的方式创建此包装器?是ContinueWith要走的路?
更新:同步抛出异常的异步操作的具体示例:
public static Task WriteAllBytesAsync(string filePath, byte[] bytes)
{
if (filePath == null)
throw new ArgumentNullException(filePath, nameof(filePath));
if (bytes == …Run Code Online (Sandbox Code Playgroud) c# ×7
.net ×2
async-await ×2
dispose ×2
asmx ×1
asp.net ×1
asynchronous ×1
idisposable ×1
java ×1
soap ×1
task ×1
web-services ×1