

























//Server model public class Book { public int Id { get; set; } public string Name { get; set; } public string ISBN { get; set; } public string Author { get; set; } public string Comment { get; set; } public string Content { get; set; } public string Summary { get; set; } public string Title { get; set; } public string Topic { get; set; } } //Client model public class BookSlim { public int Id { get; set; } public string Name { get; set; } public string ISBN { get; set; } public string Author { get; set; } }
JsonSerializerSettings setting = new JsonSerializerSettings() { MissingMemberHandling = MissingMemberHandling.Ignore }; List<BookSlim>? bksList = JsonConvert.DeserializeObject<List<BookSlim>>(jsonStr, setting);
//Consumer <Window x:Class="WpfApp5.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:WpfApp5" mc:Ignorable="d" Title="{Binding MainTitle}" WindowState="Maximized"> <Window.DataContext> <local:MainVM/> </Window.DataContext> <Grid> <DataGrid ItemsSource="{Binding BooksCollection}" VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" VirtualizingPanel.CacheLength="5,5" VirtualizingPanel.CacheLengthUnit="Item" ScrollViewer.IsDeferredScrollingEnabled="True" ScrollViewer.CanContentScroll="True" UseLayoutRounding="True" SnapsToDevicePixels="True" EnableRowVirtualization="True" EnableColumnVirtualization="True" AutoGenerateColumns="True" CanUserAddRows="False"> <DataGrid.Resources> <Style TargetType="DataGridRow"> <Setter Property="FontSize" Value="30"/> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="FontSize" Value="50"/> <Setter Property="Foreground" Value="Red"/> </Trigger> </Style.Triggers> </Style> </DataGrid.Resources> </DataGrid> </Grid> </Window> using Newtonsoft.Json; using System.Collections.ObjectModel; using System.ComponentModel; using System.Net.Http; using System.Runtime.CompilerServices; using System.Text; 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 WpfApp5 { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } } public class MainVM : INotifyPropertyChanged { HttpClient client = null; string originalUrl = "http://localhost:8080/getbookslist?count="; private bool isLoading = false; public MainVM() { if (!DesignerProperties.GetIsInDesignMode(new DependencyObject())) { client = new HttpClient(); Task.Run(async () => { await LoadDataFromServerWithoutRest(); }); } } private async Task LoadDataFromServerWithoutRest() { while (true) { await InitBooksCollectionAsync(); await Task.Delay(20000); } } private SemaphoreSlim concurrentLimit = new SemaphoreSlim(10,10); private async Task InitBooksCollectionAsync(int cnt = 1000000) { if (isLoading) { return; } bool acquired = false; try { acquired = await concurrentLimit.WaitAsync(30000); if (!acquired) { PrintMsgInOutput("Acquire concurrent signal failed"); return; } isLoading = true; await Application.Current?.Dispatcher?.InvokeAsync(() => { MainTitle = $"{DateTime.Now},loading..."; BooksCollection?.Clear(); },System.Windows.Threading.DispatcherPriority.Background); string requestUrl = $"{originalUrl}{cnt}"; string jsonStr = await client.GetStringAsync(requestUrl); if (!string.IsNullOrWhiteSpace(jsonStr)) { JsonSerializerSettings setting = new JsonSerializerSettings() { MissingMemberHandling = MissingMemberHandling.Ignore }; List<BookSlim>? bksList = JsonConvert.DeserializeObject<List<BookSlim>>(jsonStr, setting); if (bksList != null && bksList.Any()) { await Application.Current?.Dispatcher?.InvokeAsync(() => { BooksCollection = new ObservableCollection<BookSlim>(bksList); MainTitle = $"{DateTime.Now},FirstId:{BooksCollection[0]?.Id},LastId:{BooksCollection[^1]?.Id}"; }, System.Windows.Threading.DispatcherPriority.Background); } } } catch (Exception ex) { PrintMsgInOutput(ex?.Message); } finally { if(acquired) { concurrentLimit.Release(); } isLoading = false; } } private void PrintMsgInOutput(string msg) { #if DEBUG System.Diagnostics.Debug.WriteLine($"{DateTime.Now},{msg}"); #else System.Diagnostics.Trace.WriteLine($"{DateTime.Now},{msg}"); #endif } private string mainTitle = $"{DateTime.Now}"; public string MainTitle { get { return mainTitle; } set { if (value != mainTitle) { mainTitle = value; OnPropertyChanged(); } } } private ObservableCollection<BookSlim> booksCollection; public ObservableCollection<BookSlim> BooksCollection { get { return booksCollection; } set { if (value != booksCollection) { booksCollection = value; OnPropertyChanged(); } } } public event PropertyChangedEventHandler? PropertyChanged; private void OnPropertyChanged([CallerMemberName] string propName = "") { var handler = Volatile.Read(ref PropertyChanged); if (handler == null) { return; } handler?.Invoke(this, new PropertyChangedEventArgs(propName)); } } public class BookSlim { public int Id { get; set; } public string Name { get; set; } public string ISBN { get; set; } public string Author { get; set; } } } //Server
using Newtonsoft.Json;
using System.Net;
using System.Text;
using System.Xml;
namespace ConsoleApp1
{
internal class Program
{
static async Task Main(string[] args)
{
await ListenHttpRequestAsync();
}
static async Task ListenHttpRequestAsync()
{
HttpListener httpListener = new HttpListener();
string prefix = "http://*:8080/";
httpListener.Prefixes.Add(prefix);
try
{
httpListener.Start();
Console.WriteLine($"{DateTime.Now},Http service started,address:{prefix}");
Console.WriteLine($"{DateTime.Now},sample:http://localhost:8080/getbookslist?count=1000");
Console.WriteLine($"{DateTime.Now},press Ctrl+C to stop service!");
while (true)
{
HttpListenerContext context = await httpListener.GetContextAsync();
await ProcessRequestAsync(context);
}
}
catch (Exception ex)
{
Console.WriteLine($"{DateTime.Now},start service failed:{ex.Message}");
Console.WriteLine($"If no permission.please run as administrator or update the port as greater than 1024");
}
finally
{
httpListener?.Close();
}
}
private static SemaphoreSlim concurrentLimit = new SemaphoreSlim(10,10);
private static async Task ProcessRequestAsync(HttpListenerContext context)
{
bool isAcquired = await concurrentLimit.WaitAsync(30000);
if (!isAcquired)
{
context.Response.StatusCode = 503;
string errorMsg = "{\"error\":\"Server busy, please retry later\"}";
byte[] buffer = Encoding.UTF8.GetBytes(errorMsg);
context.Response.ContentType = "application/json";
await context.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
context.Response.OutputStream.Close();
return;
}
if (context?.Request?.Url?.AbsolutePath?.Contains("/favicon.ico") == true)
{
return;
}
try
{
int count = ParseCountFromRequest(context.Request);
if (count <= 0)
{
return;
}
string jsonStr = await GetJsonStrAsync(count);
context.Response.ContentType = "application/json;charset=utf-8";
context.Response.ContentEncoding = System.Text.Encoding.UTF8;
context.Response.StatusCode = 200;
byte[] buffer = Encoding.UTF8.GetBytes(jsonStr);
context.Response.ContentLength64 = buffer.Length;
await context.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
Console.WriteLine($"{DateTime.Now},request from:{context?.Request?.Url?.ToString()}," +
$"Thread Id:{Thread.CurrentThread.ManagedThreadId},length:{jsonStr.Length}\n\n");
}
catch (Exception ex)
{
Console.WriteLine($"{DateTime.Now},Process request failed:{ex.Message}");
context.Response.StatusCode = 500;
string errorMsg = $"{{\"error\":\"{ex.Message}\"}}";
byte[] buffer = Encoding.UTF8.GetBytes(errorMsg);
await context.Response.OutputStream.WriteAsync(buffer, 0, buffer.Length);
}
finally
{
if(isAcquired)
{
concurrentLimit.Release();
}
context.Response.OutputStream?.Close();
}
}
private static int ParseCountFromRequest(HttpListenerRequest request)
{
int cnt = 0;
string path = request.Url.AbsolutePath;
Console.WriteLine($"{DateTime.Now},request path:{request.Url.ToString()}");
if (path == "/getbookslist")
{
if (request.QueryString != null)
{
string countParam = request.QueryString["count"];
if (!string.IsNullOrWhiteSpace(countParam))
{
if (!int.TryParse(countParam, out cnt) || cnt < 1)
{
cnt = 0;
}
}
}
}
else if (path == "/getbook")
{
cnt = 100;
}
return cnt;
}
private static int id = 1;
private static (int, int) GetStartEnd(int interval)
{
int end = Interlocked.Add(ref id, interval);
int start = end - interval;
return (start, end);
}
static async Task<string> GetJsonStrAsync(int cnt = 1000000)
{
return await Task.Run(() =>
{
List<Book> bksList = new List<Book>();
var (start, end) = GetStartEnd(cnt);
for (int i = start; i < end; i++)
{
bksList.Add(new Book()
{
Id = i,
Name = $"Name_{i}",
ISBN = $"ISBN_{i}",
Author = $"Author_{i}",
Comment = $"Comment_{i}",
Content = $"Content_{i}",
Summary = $"Summary_{i}",
Title = $"Title_{i}",
Topic = $"Topic_{i}"
});
}
Console.WriteLine($"{DateTime.Now},Id bwtween:[{bksList.FirstOrDefault()?.Id}] and [{bksList.LastOrDefault()?.Id}]");
string jsonStr = JsonConvert.SerializeObject(bksList,Newtonsoft.Json.Formatting.None);
return jsonStr;
});
}
}
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
public string ISBN { get; set; }
public string Author { get; set; }
public string Comment { get; set; }
public string Content { get; set; }
public string Summary { get; set; }
public string Title { get; set; }
public string Topic { get; set; }
}
}


此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。