.NET Core 6 - WPF、MVC和SignalR

k2fxgqgv  于 2023-05-08  发布在  .NET
关注(0)|答案(1)|浏览(167)

我有一个WPF应用程序,当单击按钮时,它会向ASP.NET Core 6 MVC应用程序发送请求。MVC控制器中的action方法接收请求,调用一个在for循环中运行长任务的方法,我试图使用SignalR来更新WPF应用程序中的标签,其中包含正在处理的循环迭代次数。
问题:在我单击该按钮后,标签在任务期间根本不会更改,只有当任务结束时,它才会更改以显示最后一次迭代的编号。
我猜这是同步/异步的问题,但我是一个新手,似乎仍然不能理解它…
这是WPF按钮处理程序:

private async void myButton_Click(object sender, RoutedEventArgs e) {
    HubConnection connection = new HubConnectionBuilder().WithUrl("https://localhost:7036/miHub").Build();
    await connection.StartAsync();
    connection.On<string>("Notify", (str) => { lblProgress.Content = str; });

    //calls mvc controller action 
    string url = "https://localhost:7036/Sincro/procesa";

    using (var httpClient = new HttpClient()) {
        string json = await httpClient.GetStringAsync(url);
    }
}

这是控制器:

public class SincroController : Controller {
    private readonly IHubContext<MiHub> _hubContext;
    
    //ctor
    public SincroController(IHubContext<MiHub> hubContext) {
        _hubContext = hubContext;
    }
    
    public async Task<JsonResult> procesa() {
        await longProcess();
        
        var json = new { foo = "bar" };
        return Json(json);
    }
    
    private async Task<int> longProcess() {
        for(int row=0; row<5000; row++) {
            await _hubContext.Clients.All.SendAsync("Notify", $"Processing thing {row}");
        }
        return 0;
    }
}
tcomlyy6

tcomlyy61#

在你的longProcess代码中,for循环实际上非常快,试试Thread.Sleep(1500);

测试结果

优化测试代码

我的测试结果

您的代码测试结果

样本编码

  • MainWindow.xaml*
<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Button x:Name="button" Content="Invoke Api" HorizontalAlignment="Left" Margin="13,15,0,0" VerticalAlignment="Top" Click="button_Click"/>
        <Label x:Name="lblSignalrStatus" Content="" HorizontalAlignment="Left" Margin="115,13,0,0" VerticalAlignment="Top" Width="367"/>
        <Label x:Name="lblProgress" Content="" HorizontalAlignment="Left" Margin="205,45,0,0" VerticalAlignment="Top" Width="367"/>
        <TextBox x:Name="textBoxProgress" AcceptsReturn="True" HorizontalAlignment="Left" Margin="12,87,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Width="744" Height="327"/>
        <Label x:Name="label" Content="Label Content" HorizontalAlignment="Left" Margin="110,43,0,0" VerticalAlignment="Top"/>
        <Label x:Name="label1" Content="TextBox Content" HorizontalAlignment="Left" Margin="12,55,0,0" VerticalAlignment="Top"/>

    </Grid>
</Window>
  • MainWindow.xaml.cs*
using Microsoft.AspNetCore.SignalR.Client;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace WpfApp1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        HubConnection _connection;
        public MainWindow()
        {
            InitializeComponent();

            Connect();
        }

        private async void button_Click(object sender, RoutedEventArgs e)
        {

            //calls mvc controller action 
            string url = "https://localhost:44356/Test/procesa";
            using (var httpClient = new HttpClient())
            {
                string json = await httpClient.GetStringAsync(url);
            }
        }

        public async Task Connect()
        {
            _connection = new HubConnectionBuilder()
                .WithUrl($"https://localhost:44356/mainHub")
                .WithAutomaticReconnect()
                .Build();

            await _connection.StartAsync();

            lblSignalrStatus.Content = "Connection started";

            _connection.On<string>("Notify", OnNotifyHandler);

            _connection.Closed += async (error) =>
            {
                await Task.Delay(new Random().Next(0, 5) * 1000);
                await _connection.StartAsync();
            };
        }
        public Func<string, Task> NotifyHandler { get; set; }
        private void OnNotifyHandler(string str) // => NotifyHandler?.Invoke(name);
        {
            this.Dispatcher.Invoke(() =>
            {
                string dtime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "   ";
                lblProgress.Content = dtime + str;
                textBoxProgress.AppendText(dtime + str + "\r\n");
                textBoxProgress.ScrollToEnd();
            });
            
        }
    }
}

相关问题