.net core 和 WPF 开发升讯威在线客服与营销系统:使用线程安全的 BlockingCollection 实现高性能的数据处理
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程。本产品已经成熟稳定并投入商用。
在线演示环境:https://kf.shengxunwei.com 注意:演示环境仅供演示交流与评估,不保证 7x24 小时可用。
对于在线客服与营销系统,客服端指的是后台提供服务的客服或营销人员,他们使用客服程序在后台观察网站的被访情况,开展营销活动或提供客户服务。在本篇文章中,我将详细介绍如何在 .net core 环境下使用 TCP 通信技术实现稳定高效与安全的客服端程序。
这里存在几个技术难点需要注意:
- 需要使客服端程序具备 24 小时不间断运行的能力,在处理网络通信时,必须100%的稳定。
- 必须具备应对网络波动的能力,不能网络稍有波动就断线。即使出现了短暂的网络中断,客服程序也不能做掉线处理,而是要具备保持和自动重连的能力。
- 要考虑安全性问题,服务端的端口监听,要能识别正常客服端连接,还是来自攻击者的连接。
访客端实现的效果:


访客端在手机上的效果:
后台客服的实现效果:
线程安全集合
System.Collections.Concurrent 命名空间,其中包含多个线程安全且可缩放的集合类。 多个线程可以安全高效地从这些集合添加或删除项,而无需在用户代码中进行其他同步。 编写新代码时,只要将多个线程同时写入到集合时,就使用并发集合类。
细粒度锁定和无锁机制
某些并发集合类型使用轻量同步机制,如 SpinLock、SpinWait、SemaphoreSlim 和 CountdownEvent。 这些同步类型通常在将线程真正置于等待状态之前,会在短时间内使用 忙旋转。 预计等待时间非常短时,旋转比等待所消耗的计算资源少得多,因为后者涉及资源消耗量大的内核转换。 对于使用旋转的集合类,这种效率意味着多个线程能够以非常快的速率添加和删除项。
BlockingCollection
BlockingCollection 是一个线程安全集合类,可提供以下内容:
- 生成者/使用者模式的实现; BlockingCollection 是接口的包装 IProducerConsumerCollection 。
- 利用和方法并发添加和移除多个线程中的项 Add Take 。
- Add Take 当集合已满或为空时阻止和操作的绑定集合。
- Add Take 使用 CancellationToken 或方法中的对象取消或操作 TryAdd TryTake 。
下面的示例演示如何使用:
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
class BlockingCollectionDemo
{
static async Task Main()
{
await AddTakeDemo.BC_AddTakeCompleteAdding();
TryTakeDemo.BC_TryTake();
FromToAnyDemo.BC_FromToAny();
await ConsumingEnumerableDemo.BC_GetConsumingEnumerable();
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
}
class AddTakeDemo
{
// Demonstrates:
// BlockingCollection<T>.Add()
// BlockingCollection<T>.Take()
// BlockingCollection<T>.CompleteAdding()
public static async Task BC_AddTakeCompleteAdding()
{
using (BlockingCollection<int> bc = new BlockingCollection<int>())
{
// Spin up a Task to populate the BlockingCollection
Task t1 = Task.Run(() =>
{
bc.Add(1);
bc.Add(2);
bc.Add(3);
bc.CompleteAdding();
});
// Spin up a Task to consume the BlockingCollection
Task t2 = Task.Run(() =>
{
try
{
// Consume consume the BlockingCollection
while (true) Console.WriteLine(bc.Take());
}
catch (InvalidOperationException)
{
// An InvalidOperationException means that Take() was called on a completed collection
Console.WriteLine("That's All!");
}
});
await Task.WhenAll(t1, t2);
}
}
}
class TryTakeDemo
{
// Demonstrates:
// BlockingCollection<T>.Add()
// BlockingCollection<T>.CompleteAdding()
// BlockingCollection<T>.TryTake()
// BlockingCollection<T>.IsCompleted
public static void BC_TryTake()
{
// Construct and fill our BlockingCollection
using (BlockingCollection<int> bc = new BlockingCollection<int>())
{
int NUMITEMS = 10000;
for (int i = 0; i < NUMITEMS; i++) bc.Add(i);
bc.CompleteAdding();
int outerSum = 0;
// Delegate for consuming the BlockingCollection and adding up all items
Action action = () =>
{
int localItem;
int localSum = 0;
while (bc.TryTake(out localItem)) localSum += localItem;
Interlocked.Add(ref outerSum, localSum);
};
// Launch three parallel actions to consume the BlockingCollection
Parallel.Invoke(action, action, action);
Console.WriteLine("Sum[0..{0}) = {1}, should be {2}", NUMITEMS, outerSum, ((NUMITEMS * (NUMITEMS - 1)) / 2));
Console.WriteLine("bc.IsCompleted = {0} (should be true)", bc.IsCompleted);
}
}
}
class FromToAnyDemo
{
// Demonstrates:
// Bounded BlockingCollection<T>
// BlockingCollection<T>.TryAddToAny()
// BlockingCollection<T>.TryTakeFromAny()
public static void BC_FromToAny()
{
BlockingCollection<int>[] bcs = new BlockingCollection<int>[2];
bcs[0] = new BlockingCollection<int>(5); // collection bounded to 5 items
bcs[1] = new BlockingCollection<int>(5); // collection bounded to 5 items
// Should be able to add 10 items w/o blocking
int numFailures = 0;
for (int i = 0; i < 10; i++)
{
if (BlockingCollection<int>.TryAddToAny(bcs, i) == -1) numFailures++;
}
Console.WriteLine("TryAddToAny: {0} failures (should be 0)", numFailures);
// Should be able to retrieve 10 items
int numItems = 0;
int item;
while (BlockingCollection<int>.TryTakeFromAny(bcs, out item) != -1) numItems++;
Console.WriteLine("TryTakeFromAny: retrieved {0} items (should be 10)", numItems);
}
}
class ConsumingEnumerableDemo
{
// Demonstrates:
// BlockingCollection<T>.Add()
// BlockingCollection<T>.CompleteAdding()
// BlockingCollection<T>.GetConsumingEnumerable()
public static async Task BC_GetConsumingEnumerable()
{
using (BlockingCollection<int> bc = new BlockingCollection<int>())
{
// Kick off a producer task
await Task.Run(async () =>
{
for (int i = 0; i < 10; i++)
{
bc.Add(i);
await Task.Delay(100); // sleep 100 ms between adds
}
// Need to do this to keep foreach below from hanging
bc.CompleteAdding();
});
// Now consume the blocking collection with foreach.
// Use bc.GetConsumingEnumerable() instead of just bc because the
// former will block waiting for completion and the latter will
// simply take a snapshot of the current state of the underlying collection.
foreach (var item in bc.GetConsumingEnumerable())
{
Console.WriteLine(item);
}
}
}
}
本文对使用线程安全的 BlockingCollection 实现高性能的数据处理进行了简要的介绍,在接下来的文章中,我将具体解构服务端程序的结构和设计、客服端程序的结构和设计,敬请关注。
在线演示环境:https://kf.shengxunwei.com 注意:演示环境仅供演示交流与评估,不保证 7x24 小时可用。
联系QQ: 279060597
联系E-mail:C5118@outlook.com
.net core 和 WPF 开发升讯威在线客服与营销系统:使用线程安全的 BlockingCollection 实现高性能的数据处理的更多相关文章
- .net core 和 WPF 开发升讯威在线客服与营销系统:背景和产品介绍
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf-m.shengxunwei.com ...
- .net core 和 WPF 开发升讯威在线客服与营销系统:系统总体架构
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...
- .net core 和 WPF 开发升讯威在线客服与营销系统:(插曲)一次端口攻击行为的分析与应对
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...
- .net core 和 WPF 开发升讯威在线客服与营销系统:使用 WebSocket 实现访客端通信
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...
- .net core 和 WPF 开发升讯威在线客服与营销系统:使用 TCP协议 实现稳定的客服端
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...
- .net core 和 WPF 开发升讯威在线客服与营销系统:实现对 IE8 的完全完美支持 【干货】
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...
- .net core 和 WPF 开发升讯威在线客服系统:怎样实现拔网线也不丢消息的高可靠通信(附视频)
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 在线演示环境:https://kf.shengxunwei.com 注意 ...
- .net core 和 WPF 开发升讯威在线客服系统:把 .Net Framework 打包进安装程序
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程. 系列文章目录: https://blog.shengxunwei.com/Home/Post/44a3 ...
- .net core 和 WPF 开发升讯威在线客服系统:使用本地IP数据库实现访客来源快速定位,支持国外
本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 免费使用 & 私有化部署:https://kf.shengxun ...
随机推荐
- 聊聊并发,进程通信方式,go协程简单应用场景
开篇提问 知道并发,并行,线程,协程概念吗?或者知道大概含义吗? 有线程为什么还要有协程?区别是什么? 『进程』通信方式知道几种?有没有超过3种? golang『协程』通信方式推荐? 使用并发的目的是 ...
- NOIP初赛篇——10计算机网络
网络的定义 所谓计算机网络,就是利用通信线路和设备,把分布在不同地理位置上的多台计算机连接起来. 计算机网络是现代通信技术与计算机奇数结合的产物. 网络中计算机与计算机之间的通信依靠协议进 ...
- Mysql-Incorrect string value
[问题描述] com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect string value: '\xF0\x9F\x8E\x8 ...
- 【C++】《Effective C++》第七章
第七章 模板与泛型编程 条款41:了解隐式接口和编译期多态 面向对象设计中的类(class)考虑的是显式接口(explict interface)和运行时多态,而模板编程中的模板(template)考 ...
- CopyOnWriteArrayList设计思路与源码分析
CopyOnWriteArrayList实现了List接口,RandomAccess,Cloneable,Serializable接口. CopyOnWriteArrayList特性 1.线程安全,在 ...
- MySQL全面瓦解17:触发器相关
关于触发器 现实开发中我们经常会遇到这种情况,比如添加.删除和修改信息的时候需要记录日志,我们就要在完成常规的数据库逻辑操作之后再去写入日志表,这样变成了两步操作,更复杂了. 又比如删除一个人员信息的 ...
- 【Not BUG】微软Winform窗体中设计上的Bug,会导致程序编译失败?不,这不是BUG!
这不是BUG!!! 原文地址: https://www.cnblogs.com/thanks/p/14302011.html 现在让我们回忆一下原文 原文的操作步骤: 1. 新建一个Window Fo ...
- C# 中的动态类型
翻译自 Camilo Reyes 2018年10月15日的文章 <Working with the Dynamic Type in C#> [1] .NET 4 中引入了动态类型.动态对象 ...
- WTM5.0发布,全面支持.net5
WTM5.0是WTM框架开源2年以来最大的一次升级,全面支持.net5,大幅重构了底层代码,针对广大用户提出的封装过度,不够灵活,性能不高等问题进行了彻底的修改. 这次升级使WTM继续保持开箱即用,高 ...
- [Usaco2007 Dec]Building Roads 修建道路
题目描述 Farmer John最近得到了一些新的农场,他想新修一些道路使得他的所有农场可以经过原有的或是新修的道路互达(也就是说,从任一个农场都可以经过一些首尾相连道路到达剩下的所有农场).有些农场 ...