SSIS脚本组件调用Azure翻译API触发BufferDisconnectedException的问题及异步方法整合咨询
解决SSIS脚本组件中调用Azure翻译API的BufferDisconnectedException问题
你的问题核心在于SSIS脚本组件的同步执行上下文和异步API调用的冲突——你用了async void修饰Input0_ProcessInputRow方法,这会导致SSIS运行时误以为行处理已经完成,提前释放输入缓冲区,而此时你的异步翻译请求还在后台运行,最终触发Dts.Pipeline.BufferDisconnectedException。
微软官方示例用async Task Main是因为控制台程序支持异步入口点,但SSIS的Input0_ProcessInputRow是固定的同步方法签名,不能直接用async void(这种写法只适合事件处理场景,非事件场景下会丢失任务跟踪能力)。
解决方案:将异步API调用同步化
我们可以把翻译逻辑封装成异步方法,然后在同步的Input0_ProcessInputRow中同步等待异步操作完成,避免SSIS提前释放缓冲区。以下是修正后的完整代码:
public class ScriptMain : UserComponent { private static readonly string subscriptionKey = "###########"; private static readonly string endpoint = "https://api.cognitive.microsofttranslator.com"; private static readonly string location = "global"; // 封装异步翻译逻辑 private static async Task<string> TranslateTextAsync(string textToTranslate) { ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; string route = "/translate?api-version=3.0&from=de&to=en"; object[] body = new object[] { new { Text = textToTranslate } }; var requestBody = JsonConvert.SerializeObject(body); using (var client = new HttpClient()) using (var request = new HttpRequestMessage()) { request.Method = HttpMethod.Post; request.RequestUri = new Uri(endpoint + route); request.Content = new StringContent(requestBody, Encoding.UTF8, "application/json"); request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey); request.Headers.Add("Ocp-Apim-Subscription-Region", location); HttpResponseMessage response = await client.SendAsync(request).ConfigureAwait(false); return await response.Content.ReadAsStringAsync().ConfigureAwait(false); } } public override void Input0_ProcessInputRow(Input0Buffer Row) { try { // 同步等待异步操作完成,确保SSIS不会提前释放缓冲区 string translationResult = TranslateTextAsync(Row.TextToTranslate).GetAwaiter().GetResult(); Row.TranslationFromAPI = translationResult; } catch (Exception ex) { // 可选:添加错误处理,比如记录错误信息到输出列 Row.ErrorDescription = $"翻译失败:{ex.Message}"; // 标记此行错误(如果需要让SSIS路由到错误输出) // Row.DirectRowToErrorOutput(); } } }
关键细节说明:
- 避免
async void:async void会让方法在第一个await时立即返回,SSIS会认为行处理完成并释放缓冲区,后续异步操作完成后再访问Row就会报错。 - 使用
GetAwaiter().GetResult():相比.Wait(),它会直接抛出原始异常,便于调试;配合ConfigureAwait(false)可以避免上下文死锁风险。 - 错误处理:添加
try-catch块可以防止单个行的翻译失败导致整个数据流任务崩溃,同时可以把错误信息写入自定义列,方便后续排查问题。
内容的提问来源于stack exchange,提问作者MichaelJS
相关产品推荐
相关产品推荐

