C#控制台程序上传Dropbox时MemoryStream引发程序重启无异常问题
解决C#控制台程序DropboxClient初始化后重启问题
问题分析
程序执行到DropboxClient dbx = new DropboxClient(oAuthResponse.access_token);后无异常重启,核心原因大概率是未捕获的致命异常导致程序崩溃,或者MakeRequestAsync返回的OAuthResponse存在无效值(如空access_token)触发了DropboxClient构造函数内部的未处理异常。
解决方案步骤
1. 校验OAuthResponse的有效性
在创建DropboxClient前,先检查access_token是否为空或无效,避免构造函数接收非法参数:
var oAuthResponse = await MakeRequestAsync(); // 新增校验逻辑,拦截无效token if (string.IsNullOrEmpty(oAuthResponse.access_token)) { Console.WriteLine("获取的Access Token无效,请检查OAuth请求配置"); return; // 或抛出异常终止流程,避免后续错误 } DropboxClient dbx = new DropboxClient(oAuthResponse.access_token);
2. 注册全局未捕获异常处理
控制台程序中异步代码的未捕获异常可能直接导致程序终止,注册全局异常事件可以捕获根源问题:
在Main方法开头添加以下代码:
// 捕获AppDomain级别的未处理异常 AppDomain.CurrentDomain.UnhandledException += (sender, e) => { var ex = e.ExceptionObject as Exception; Console.WriteLine($"未处理异常:{ex?.Message}\n堆栈信息:{ex?.StackTrace}"); Console.ReadKey(); // 阻止程序立即退出,方便查看错误详情 }; // 捕获Task未观察到的异常 TaskScheduler.UnobservedTaskException += (sender, e) => { Console.WriteLine($"未观察到的Task异常:{e.Exception.Message}\n堆栈信息:{e.Exception.StackTrace}"); e.SetObserved(); // 标记异常已处理,避免程序强制终止 Console.ReadKey(); };
3. 确保异步入口的正确实现
如果你的Main方法是void Main,改为async Task Main(C# 7.1及以上版本支持),确保异步调用能被正确等待,避免上下文丢失:
static async Task Main(string[] args) { // 先注册全局异常处理 AppDomain.CurrentDomain.UnhandledException += ...; TaskScheduler.UnobservedTaskException += ...; // 原有业务代码逻辑 var filePath = startupPath + "\\" + $"test-{house.Id}.png"; var oAuthResponse = await MakeRequestAsync(); // ...后续代码 }
4. 优化MakeRequestAsync的错误处理
当前方法在请求失败时返回空OAuthResponse,容易导致后续代码隐性出错,改为抛出异常让上层处理:
public static async Task<OAuthResponse> MakeRequestAsync() { using (var httpClient = new HttpClient()) { string url = "https://api.dropbox.com/oauth2/token"; string clientId = "My_Key"; string clientSecret = "My_Client_Secret"; var byteArray = System.Text.Encoding.ASCII.GetBytes($"{clientId}:{clientSecret}"); httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray)); var formData = new Dictionary<string, string> { { "grant_type", "refresh_token" }, { "refresh_token", "My_Token" } }; try { HttpResponseMessage response = await httpClient.PostAsync(url, new FormUrlEncodedContent(formData)); response.EnsureSuccessStatusCode(); // 直接抛出HTTP错误异常,替代手动判断状态码 string content = await response.Content.ReadAsStringAsync(); OAuthResponse oauthResponse = System.Text.Json.JsonSerializer.Deserialize<OAuthResponse>(content)!; Console.WriteLine("Access Token: " + oauthResponse.access_token); Console.WriteLine("Token Type: " + oauthResponse.token_type); Console.WriteLine("Expires In: " + oauthResponse.expires_in); return oauthResponse; } catch (Exception e) { Console.WriteLine($"OAuth请求错误: {e.Message}"); throw; // 抛出异常让上层处理,而非返回空对象 } } }
关键说明
- 无异常重启本质是未被捕获的致命异常,全局异常处理能帮你定位具体错误原因。
- 不要忽略
MakeRequestAsync的错误返回,空token传入DropboxClient构造函数可能触发内部未公开的异常。 - 控制台程序的异步入口必须正确实现,否则异步操作的上下文丢失会引发隐性异常。
内容的提问来源于stack exchange,提问作者Shahin Babayev
相关产品推荐
相关产品推荐

