C#: ObjectDisposedException
C#で破棄されたオブジェクトにアクセスした際のエラー原因と解決策
概要
Dispose()が呼ばれた後のオブジェクトにアクセスした際に発生するエラーです。
エラーメッセージ
``` System.ObjectDisposedException: Cannot access a disposed object. Object name: ‘HttpClient’. ```
原因
- using後のアクセス: usingブロック外での使用
- 非同期処理の競合: Disposeとawaitのタイミング
- 共有リソースの早期破棄: シングルトンのHttpClient等
- イベントハンドラでの参照: 破棄後もイベントが発火
解決策
1. usingのスコープを確認
```csharp // 悪い例 HttpResponseMessage response; using (var client = new HttpClient()) { response = await client.GetAsync(url); } var content = await response.Content.ReadAsStringAsync(); // エラー
// 良い例 using (var client = new HttpClient()) { var response = await client.GetAsync(url); var content = await response.Content.ReadAsStringAsync(); // OK } ```
2. HttpClientは共有する
```csharp // 悪い例: 毎回新規作成 public async Task GetData() { using var client = new HttpClient(); return await client.GetStringAsync(url); }
// 良い例: IHttpClientFactoryを使用 public class MyService { private readonly HttpClient _client;
public MyService(IHttpClientFactory factory)
{
_client = factory.CreateClient();
}
public async Task<string> GetData()
{
return await _client.GetStringAsync(url);
}
} ```
3. 非同期Dispose (C# 8.0+)
```csharp public class AsyncResource : IAsyncDisposable { public async ValueTask DisposeAsync() { await CleanupAsync(); } }
// 使用 await using var resource = new AsyncResource(); await resource.DoWorkAsync(); ```
4. 破棄チェックを追加
```csharp public class MyResource : IDisposable { private bool _disposed = false;
public void DoWork()
{
if (_disposed)
throw new ObjectDisposedException(nameof(MyResource));
// 処理
}
public void Dispose()
{
_disposed = true;
// クリーンアップ
}
} ```
よくある間違い
- HttpClientを毎回newしてDispose
- 非同期メソッドの結果を待たずにDispose
- Disposeの順序が不適切
関連エラー
関連エラー
C# の他のエラー
この記事は役に立ちましたか?