You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF中自托管Web API遇请求超时问题求解决方案

WPF中自托管Web API超时问题的解决方案

问题根源分析

你的实现存在三个关键问题,直接导致请求超时:

  1. UI线程死锁:在MainWindow构造函数中同步调用异步方法GetCall(),WPF的UI线程是单线程上下文,await会试图回到UI线程继续执行,但此时构造函数已经阻塞了UI线程,导致请求一直无法完成,最终触发超时。
  2. 中间件与路由顺序错误:UseWebApi在UseCors之前调用,导致CORS中间件无法正确生效;同时属性路由配置在默认路由之后,不符合路由优先级规则。
  3. 未持有WebApp实例:WebApp.Start返回的IDisposable未被保存,垃圾回收可能会回收服务器进程,导致请求无响应。

修复步骤与代码示例

1. 修正UI线程异步调用逻辑

不要在构造函数中直接调用异步方法,改用Loaded事件处理异步操作,并持有WebApp实例防止被GC回收:

using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.Owin.Hosting;

namespace WpfApp3
{
    public partial class MainWindow : Window
    {
        private readonly string _baseAddress = "http://localhost:4444/";
        private IDisposable _webAppHost;

        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }

        private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            // 启动自托管API并持有实例,防止被GC回收
            _webAppHost = WebApp.Start<StartUp>(_baseAddress);
            // 异步调用API,避免阻塞UI线程
            await CallDemoApi();
        }

        private async Task CallDemoApi()
        {
            using (HttpClient client = new HttpClient())
            {
                try
                {
                    var response = await client.GetStringAsync($"{_baseAddress}api/demo");
                    // 处理返回结果,如需更新UI请使用Dispatcher
                    // Dispatcher.Invoke(() => { ResultTextBlock.Text = response; });
                }
                catch (Exception ex)
                {
                    // 异常处理
                    Console.WriteLine(ex.Message);
                }
            }
        }

        // 窗口关闭时释放API主机资源
        protected override void OnClosed(EventArgs e)
        {
            _webAppHost?.Dispose();
            base.OnClosed(e);
        }
    }
}

2. 修正StartUp类的中间件与路由顺序

调整CORS中间件和WebAPI的顺序,同时确保属性路由优先配置:

using Owin;
using System.Web.Http;

namespace WpfApp3
{
    public class StartUp
    {
        public void Configuration(IAppBuilder appBuilder)
        {
            // 先启用CORS中间件,确保请求被正确拦截
            appBuilder.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);

            HttpConfiguration config = new HttpConfiguration();
            config.EnableCors();
            
            // 优先配置属性路由,再配置默认路由
            config.MapHttpAttributeRoutes();
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );

            // 最后挂载WebAPI中间件
            appBuilder.UseWebApi(config);
        }
    }
}

替代方案:使用ASP.NET Core自托管

旧的OWIN自托管已逐渐被ASP.NET Core替代,后者性能更好、生态更完善,更适合WPF场景:

using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

namespace WpfApp3
{
    public partial class MainWindow : Window
    {
        private readonly string _baseAddress = "http://localhost:4444/";
        private IHost _apiHost;

        public MainWindow()
        {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }

        private async void MainWindow_Loaded(object sender, RoutedEventArgs e)
        {
            // 构建ASP.NET Core主机
            _apiHost = Host.CreateDefaultBuilder()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseUrls(_baseAddress);
                    webBuilder.ConfigureServices(services =>
                    {
                        services.AddControllers();
                        services.AddCors(options =>
                        {
                            options.AddPolicy("AllowAll", policy =>
                            {
                                policy.AllowAnyOrigin()
                                      .AllowAnyMethod()
                                      .AllowAnyHeader();
                            });
                        });
                    });
                    webBuilder.Configure(app =>
                    {
                        app.UseCors("AllowAll");
                        app.UseRouting();
                        app.UseEndpoints(endpoints =>
                        {
                            endpoints.MapControllers();
                        });
                    });
                })
                .Build();

            // 启动主机
            await _apiHost.StartAsync();
            await CallDemoApi();
        }

        private async Task CallDemoApi()
        {
            using (HttpClient client = new HttpClient())
            {
                try
                {
                    var response = await client.GetStringAsync($"{_baseAddress}api/demo");
                    // 处理结果
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }

        protected override async void OnClosed(EventArgs e)
        {
            if (_apiHost != null)
            {
                await _apiHost.StopAsync();
                _apiHost.Dispose();
            }
            base.OnClosed(e);
        }
    }
}

内容的提问来源于stack exchange,提问作者praveena H M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 06:10:15