09-C#

C# 精确转换WGS84、GCJ02、BD09坐标系:实现与优化 这些坐标系之间存在一定的偏差和转换关系,特别是在中国境内,WGS84与GCJ02、BD09之间的坐标存在不同程度的偏移。通过理解这些坐标系之间的偏差以及转换算法,我们可以在实际应用中,尤其是在中国境内的地图和定位服务中,准确处理经纬度数据。在实际开发中,根据不同的需求选择适合的坐标转换算法,并对转换精度进行优化,是确保地理定位准确性和可靠性的关键。WGS84到GCJ02的转换存在一定的数学模型,通常是通过一定的偏移量来实现。中进行这些坐标系的相互转换,并且在高精度要求的场景下,提供相关的转换算法。 阅读详情

C#.Net-多线程-基础篇-学习笔记

一、核心概念理解

1.1 进程与线程

进程(Process)

  • 计算机中的虚拟记录,描述应用程序运行时消耗的各种资源集合
  • 包含:CPU + 内存 + 磁盘IO + 网络资源
  • 类比:一个公司的整体运作

线程(Thread)

  • 程序进程中执行具体动作的最小执行流
  • 从点击按钮到网络通信,都是线程在执行
  • 类比:公司中的具体员工
  • 特点:线程依附于进程存在,进程消失则线程也消失

句柄(Handle)

  • long类型的数字,对应程序中的某个小部件
  • 是操作程序的最小单位标识

1.2 多线程的原理

CPU与多线程

  • 例如:6核12线程的CPU
  • 通过逻辑切分,将每个核心的执行时间分片
  • 每毫秒可执行的动作被切分成10000份

执行特点

  • 宏观:多个动作在一段时间内看似同时执行完毕(并发)
  • 微观:同一时刻只能处理一件事(串行)
  • 操作系统不断调度,动作A开始用某一分片,结束时可能用另一分片

二、同步与异步

2.1 同步方法(Sync)

特点

private void DoSomethingSync()
{
    // 线性执行,从上往下依次执行
    Console.WriteLine("步骤1");
    Thread.Sleep(1000);
    Console.WriteLine("步骤2");
    Thread.Sleep(1000);
    Console.WriteLine("步骤3");
}

优点

  • 符合人类思维逻辑,代码易读
  • 有序执行,结果可预测
  • 消耗计算机资源少

缺点

  • 执行慢,会卡顿界面
  • 只有一个线程(主线程/UI线程)参与计算
  • CPU忙碌时无暇处理其他任务

生活类比

  • 真心请人吃饭:Richard请Vn吃饭,Vn说还要忙一会儿,Richard说"那我等你,忙完一起去"

2.2 异步方法(Async)

特点

private void DoSomethingAsync()
{
    // 开启新线程执行
    Task.Run(() =>
    {
        Console.WriteLine("步骤1");
        Thread.Sleep(1000);
    });
    
    Task.Run(() =>
    {
        Console.WriteLine("步骤2");
        Thread.Sleep(1000);
    });
    
    // 主线程不等待,继续执行
    Console.WriteLine("主线程继续");
}

优点

  • 执行快,不卡顿界面
  • 多个线程并发执行
  • 提高程序响应能力

缺点

  • 无序执行,结果不可预测
  • 消耗更多计算机资源
  • 编程复杂度增加

生活类比

  • 客气请人吃饭:Richard客气地请Vn吃饭,Vn说还要忙一会儿,Richard说"那你先忙,我先去吃了"

核心理念

  • 以资源换时间:使用大量资源,降低时间成本

三、C#中的多线程实现

3.1 Thread(最原始)

Thread thread = new Thread(() =>
{
    Console.WriteLine("Thread执行");
});
thread.Start();
thread.IsBackground = true;  // 后台线程:进程结束,线程随之消失
thread.IsBackground = false; // 前台线程:进程结束,线程执行完才消失

3.2 ThreadPool(线程池)

  • 管理一组可重用的线程
  • 避免频繁创建和销毁线程的开销
// 将工作项加入线程池队列
ThreadPool.QueueUserWorkItem(state =>
{
    Console.WriteLine($"ThreadPool执行,线程ID: {Thread.CurrentThread.ManagedThreadId}");
});

// 带参数版本
ThreadPool.QueueUserWorkItem(state =>
{
    string msg = (string)state;
    Console.WriteLine($"参数: {msg}");
}, "hello");

⚠️ ThreadPool 无法精确控制线程,也不支持返回值和取消,实际开发中优先使用 Task。

3.3 Task(推荐使用)

Task的优势

  • .NET Framework 3.0时代实现
  • C#中多线程操作的最佳实现
  • 丰富的API,满足各种开发场景
  • Task操作的线程来自线程池

Task开启方式

// 方式1:new Task + Start
Task task = new Task(() =>
{
    Console.WriteLine("Task执行");
});
task.Start();

// 方式2:Task.Run(推荐)
Task.Run(() =>
{
    Console.WriteLine("Task执行");
});

// 方式3:TaskFactory
TaskFactory factory = new TaskFactory();
factory.StartNew(() =>
{
    Console.WriteLine("Task执行");
});

// 方式4:带返回值
Task<int> task = Task.Run(() =>
{
    return DateTime.Now.Year;
});

线程标识

// 通过线程ID确定是否为同一线程
int threadId = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine($"当前线程ID: {threadId:00}");

四、Task的核心方法

4.1 等待方法

Wait() - 单个任务等待

Task task = Task.Run(() =>
{
    Thread.Sleep(3000);
    Console.WriteLine("任务完成");
});

task.Wait(); // 主线程等待,会卡顿界面
task.Wait(1000); // 限时等待,过时不候
task.Wait(TimeSpan.FromMilliseconds(1100)); // 使用TimeSpan

WaitAll() - 等待所有任务

List<Task> tasks = new List<Task>();
tasks.Add(Task.Run(() => DoWork1()));
tasks.Add(Task.Run(() => DoWork2()));
tasks.Add(Task.Run(() => DoWork3()));

Task.WaitAll(tasks.ToArray()); // 等待所有任务完成

WaitAny() - 等待任意一个任务

Task.WaitAny(tasks.ToArray()); // 任意一个任务完成即返回

4.2 回调方法(不阻塞)

ContinueWith() - 单个任务回调

Task task = Task.Run(() =>
{
    Thread.Sleep(3000);
    return "结果";
});

task.ContinueWith(t =>
{
    Console.WriteLine($"任务完成,结果:{t.Result}");
});

ContinueWhenAny() - 任意一个完成时回调

TaskFactory factory = new TaskFactory();
factory.ContinueWhenAny(tasks.ToArray(), completedTask =>
{
    Console.WriteLine("有一个任务完成了");
    // 不卡顿界面,用户体验好
});

ContinueWhenAll() - 所有完成时回调

factory.ContinueWhenAll(tasks.ToArray(), completedTasks =>
{
    Console.WriteLine("所有任务都完成了");
});

4.3 Delay() - 延迟执行

// Thread.Sleep - 阻塞主线程
Thread.Sleep(3000); // 主线程卡顿3秒

// Task.Delay - 不阻塞,配合ContinueWith使用
Task.Delay(3000).ContinueWith(t =>
{
    Console.WriteLine("3秒后执行");
    // 可能是新线程,也可能是主线程执行
});

五、应用场景

5.1 适合使用多线程的场景

场景1:多个独立任务并发执行

// 同时查询接口、缓存、数据库
List<Task> tasks = new List<Task>();
tasks.Add(Task.Run(() => QueryFromApi()));
tasks.Add(Task.Run(() => QueryFromCache()));
tasks.Add(Task.Run(() => QueryFromDatabase()));
Task.WaitAll(tasks.ToArray());

场景2:项目实战 - 多人协作开发

// 每个开发人员对应一个线程
TaskFactory factory = new TaskFactory();
List<Task> devTasks = new List<Task>();

devTasks.Add(factory.StartNew(() => Coding("张三", "权限模块")));
devTasks.Add(factory.StartNew(() => Coding("李四", "支付模块")));
devTasks.Add(factory.StartNew(() => Coding("王五", "订单模块")));

// 任意一人完成,准备环境
factory.ContinueWhenAny(devTasks.ToArray(), t =>
{
    Console.WriteLine("有人完成了,开始准备环境");
});

// 所有人完成,庆祝
factory.ContinueWhenAll(devTasks.ToArray(), t =>
{
    Console.WriteLine("所有人完成,一起吃饭庆祝");
});

5.2 实际业务场景

场景1:数据查询优先级

  • 同时查询缓存、数据库、第三方接口
  • 使用WaitAny,哪个先返回数据就用哪个
  • 其他线程自动放弃

场景2:首页数据加载

  • 首页包含:考勤信息、年度Top10、季度Top10、公告、通知
  • 每个模块开启一个线程并发查询
  • 使用WaitAll等待所有数据,组装后返回前端
  • 提高查询性能

5.3 不适合使用多线程的场景

  • 单个数据库查询(只有一个动作)
  • 简单的顺序操作
  • 需要严格顺序的业务逻辑

六、父子线程

Task parentTask = new Task(() =>
{
    Console.WriteLine("父线程开始");
    
    Task childTask1 = new Task(() =>
    {
        Thread.Sleep(1000);
        Console.WriteLine("子线程1");
    });
    
    Task childTask2 = new Task(() =>
    {
        Thread.Sleep(1000);
        Console.WriteLine("子线程2");
    });
    
    childTask1.Start();
    childTask2.Start();
    
    // 如果不等待子线程,父线程可能先结束
    // childTask1.Wait();
    // childTask2.Wait();
    
    Console.WriteLine("父线程结束");
});

parentTask.Start();
parentTask.Wait(); // 主线程等待父线程

注意事项

  • 父线程等待时,子线程可能还未执行完
  • 需要在父线程中显式等待子线程
  • 否则父线程结束,子线程内容可能未执行完

七、实用技巧

7.1 线程ID格式化

// 格式化为两位数,方便查看
string threadId = Thread.CurrentThread.ManagedThreadId.ToString("00");
Console.WriteLine($"线程ID: {threadId}");

7.2 时间戳格式化

string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff");
Console.WriteLine($"时间: {timestamp}");

7.3 性能测试

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

// 执行任务
DoSomething();

stopwatch.Stop();
Console.WriteLine($"耗时: {stopwatch.ElapsedMilliseconds}ms");

八、小结

  • 同步方法:有序、慢、阻塞、资源消耗少
  • 异步方法:无序、快、不阻塞、资源消耗多
  • Task 是首选:功能强大、API 丰富、来自线程池
  • Wait 系列:阻塞主线程,会卡顿界面
  • Continue 系列:不阻塞,用户体验好
  • 合理使用多线程:并发场景才使用,不要滥用
坐标转换C#(Gcj02、wgs84、bd09互转) using System; using System.Collections.Generic; using System.Text; namespace GMap.NET.Util { public static class ConvertGPS { private static double pi = 3.1415926535897932384626; private static double... 阅读详情

相关推荐

不用再找了!国测局GCJ-02与百度BD-09坐标转换的完整C#实现(WinForm版)

本文为C#开发者提供了国测局GCJ-02与百度BD-09坐标系之间完整、健壮的转换实现方案,并附带实用的WinForm工具。文章深入解析了WGS84、GCJ-02和BD-09三大坐标系的关系与转换原理,提供了可直接集成的高精度算法库、批量处理工具及工程化实践指南,解决了中国地区地图开发中坐标偏移的核心痛点。

weixin_29207533的博客 270

C#笔记09 数组

C#笔记09 数组 ——本系列是基于人民邮电出版社《C#2008 C#图解教程》、清华大学出版社《C#入门经典(第五版)》两本书的自学C#笔记,如果您发现了本文的纰漏,还望不吝指正。 写在前边 *复习:类型是一种模版,C#提供了15种预定义类型,还可以创建自己的用户定义类型,有6种类型: 类类型(class) 结构类型(struct) 数组类型(array) 枚举类型(enum) 委托类型(delegate) 接口类型(interface) 1. 什么是数组 数组实际上是由一个变量名称表示的一组同类型

Tervor_HAN的博客 518

C# 实现高精度地图坐标转换:WGS84、GCJ02与BD09的算法优化与实践

本文详细介绍了C#实现高精度地图坐标转换的方法,涵盖WGS84、GCJ02与BD09坐标系之间的算法优化与实践。通过核心代码示例和性能优化建议,帮助开发者掌握坐标转换技术,提升定位精度,适用于物流追踪、测绘等应用场景。

weixin_27032989的博客 469

GPS坐标系转换 GPS距离计算 百度转高德 wgs/gcj/BD09互转 C#函数

C#类,提供不同坐标系下的GPS互转功能

dyy123 866

C# 高精度坐标转换实战:WGS84、GCJ02与BD09互转算法优化与性能对比

本文深入探讨了C#中WGS84、GCJ02与BD09坐标系的高精度互转算法。针对地图应用开发中常见的定位偏差问题,详细解析了核心转换原理,并提供了C#实现代码。重点对比了不同逆向转换方法(如一次逼近法与二分逼近法)的精度与性能,并分享了查表法、牛顿迭代法等优化策略,帮助开发者在不同场景下平衡精度与效率需求。

weixin_29291069的博客 178

技术周总结 09.09~09.15周日(C# WinForm WPF 软件架构)

是 Windows Forms 中控件的一部分,用于表示控件中的所有行的集合。是一个非常强大的控件,可以用来显示和管理数据表格。以下是一些常用的。

xinkuaile的专栏 1505

C#小练习09

定义一个公司员工类,包含员工的员工号,姓名,性别,出生年月,年龄,工资金额等字段和属性,其中规定姓名不能为空,工资金额不低于当地最低工资600元,员工号从1000到5999,并给出将员工所有信息打印出来的ToString()方法。    using System; using System.Collections.Generic; using System.Linq; using Syste

哎一入江湖岁月催的专栏 1031

C#实战:如何在不同地图平台(WGS84/GCJ02/BD09)间实现毫秒级坐标转换?

本文深入探讨了在C#中实现WGS84、GCJ02和BD09坐标系间毫秒级转换的实战优化策略。针对车载导航、物流轨迹等高并发场景,文章从算法原理、性能瓶颈分析入手,详细介绍了数学计算优化、内存缓存、并行计算及SIMD硬件加速等关键技术,帮助开发者将单点转换耗时从0.5毫秒降至0.05毫秒以内,显著提升系统吞吐量。

weixin_29313547的博客 345

2020-09-18 C#的接口

C#的接口 文章目录C#的接口前言一、什么是接口二、实例总结 前言 今天学习C#的接口,虽然我还是不太明白接口的便利性,但先学着呗!/font> 一、什么是接口 定义:接口是一种约束形式,其中只包括成员定义,不包含成员实现的内容。 目的:接口的主要目的是为不相关的类提供通用的处理服务,由于C#中只允许树形结构中的单继承,即一个类只能继承一个父类,所以接口是让一个类具有两个以上基类的唯一方式。 声明:接口声明的方式与声明类的方式相似,但使用的关键字是interface,而不是 class。 接

AndreaXsy的博客 170

深度学习的unfold操作

对于彩色图像这样的三维数据,unfold操作会对每个通道分别进行上述的二维展开操作。例如,一个 RGB 图像,在对其进行unfold操作时,红色通道、绿色通道和蓝色通道的数据都会被独立地按照定义的窗口和步长展开,然后将这些展开后的通道数据按照原来的通道顺序组合在一起,形成新的张量。与我们熟悉的卷积类似,unfold也是使用一个特定大小的窗口和步长自左至右、自上至下滑动,不同的是,卷是滑动后与核求乘积(所以取名为卷积),而unfold滑动后不求乘积,是将窗口内的数据展开。

xulibo5828的博客 2163

双通道中频信号数字下变频及相位差估计(FPGA)

双通道中频信号数字下变频及相位差估计实验 一、上框图(通俗易懂) 二、实验要求 1、 用点频信号模拟中频信号:中频信号由DDS1和DDS2产生。具体产生方法见第2点。 2、 DDS1和 DDS2:调用IPcore里的数字信号处理中的NCO模块,工作时钟为100MHz,数据率即为100MHz,DDS1和DDS2的频率为:(学号后三位+500)Khz+f0(可设为20MHz);输出为16位;DDS1...

qq_39809425的博客 6939

2021-09-09 C# 基础 Part 1

.Net 基础 Part 1 .Net 是一个平台,是一种技术 c# 是一种编程语言 .Net 能做什么?——可以做桌面应用程序、Internet 应用程序、WP8、Uniy3D、虚拟现实 两种交互模式——C/S,客户机(Client)/服务器模式(Server),如qq,客服端需要安装专用的客户端软件,winform应用程序;B/S,浏览器(Browser)/服务器模式(Server),客户机上只需安装浏览器,Internet应用程序。 IDE,Integrated Development Enviro

Coraaaaaaaaa 176

YALMIP介绍及怎么在Matlab中加YALMIP、SDPT3

目录YALMIP简介怎么在Matlab中加YALMIP?1. 创建决策变量:2. 添加约束:3. 参数配置4. 求解怎么在MatlabR2019a中加YALMIP?1.下载工具包2.放置工具包3.添加路径4.测试安装结果怎么在MatlabR2019a中加SDPT3? YALMIP简介 怎么在Matlab中加YALMIP? yalmip是一位“集大成者”,它不仅自己包含基本的线性规划求解算法,比如linprog(线性规划)、bintprog(二值线性规划)、bnb(分支界定算法)等,他还提供了对cpl

m0_51431440的博客 2万+

C#图解教程笔记09——语句

分为条件语句、循环语句、跳转语句。条件语句包含if、if...else、switch;循环语句包含while、do、for、foreach;跳转语句包含break、continue、return、goto、throw。注意C#测试表达式必须返回bool类型的值,数字没有bool意义。

S_Yu_Tong的博客 1121

深入CARLA地图底层:OpenDRIVE文件如何影响你的仿真效果与避坑指南

本文深入解析CARLA仿真中OpenDRIVE地图文件的核心作用,揭示其如何影响车道连接、交通规则和导航逻辑。通过实战案例和代码示例,提供五大典型地图问题的诊断与修复方案,帮助开发者优化仿真效果并规避常见陷阱。

weixin_34180452的博客 276

day09 c# ArrayList的用法

using System; using System.Collections; namespace day09 { public class Student { public string name; public int age; public float height; public string sex; ...

做游戏啦 219

基于YOLOv8n的FPGA无PS端PL部署完整实现方案

本文提出了一种将YOLOv8n目标检测模型完整部署到FPGA纯PL端的实现方案。通过PyTorch训练和INT8量化技术,结合Vitis AI工具链,将模型转换为适合FPGA实现的硬件描述。方案详细阐述了从模型训练、量化校准到FPGA硬件设计的全流程,重点解决了无PS端部署的架构设计、资源优化和实时性保障等关键技术挑战。实验结果表明,该方案在Xilinx Virtex-690T FPGA上实现了30FPS以上的实时目标检测性能,为边缘计算场景提供了高效的硬件加速解决方案。

huanghm88的专栏 506

C#基础 [09] 属性

C#基础 [09] 属性 一、属性的定义和特征   1.属性的定义     属性是表示类或类的实例中的一个数据项的成员:它提供灵活的机制来读取、编写或计算某个私有字段的值。可以像使用公共数据成员一样使用属性,但实际上它们是称作“访问器”的特殊方法。这使得可以轻松访问数据,此外还有助于提高方法的安全性和灵活性。   2.属性的特征     1).属性是命名的类成员,它有类型,可

linuxheik的专栏 565

【原理图PCB专题】Allegro模块化移动器件报...has the LOCKED property怎么解锁?

正常来说做好一个模块化,如果不需要再动,最好还是lock,防止不明白的工程师异动导致问题。如果复用布局设计时,因为有些器件和拓扑并不完全一致,那需要调整部分器件,被锁之后只能全选,无法修改。所以解开锁定后,就能正常编辑了。

一点硬件 2391

大唐杯历届省赛押题训练(6)

考试-TD-LTE无线网络设备介绍-TD-LTE网络架构一、单选题1TD-LTE的接入网E-UTRAN由下列哪些网元组成( )。0分/1分A、RNCB、BTSC、eNode BD、Node B提交答案:B正确答案:C考点TD-LTE网络架构解析暂无试题解析二、多选题1关于LTE网络整体结构,哪些说法是正确的( )0分/2分A、E-UTRAN用E-NodeB替代原有的RNC-NodeB结构B、E-NodeB间的接口为S1接口C、各网络节点之间的接口使用IP传输。

nimo观察者 633

C#之入门总结_字符串_09

字符串 特性:不可变性,字符串可以看成数组,但是只能读取不能修改.             string str = string.Format("姓名:{0},年龄:{1}", "小明", 10);             Console.WriteLine(str); Fotmat.拼接成固定模式,             bool ret = string.IsNullOrEmpt

wy小骑士 355

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

C# 01.09 快捷按键

快捷按键

m0_60538503的博客 1486

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

【C#学习笔记09】线程的使用

在Window应用程序,常常需要执行长时间的运行操作,例如比较复杂的算数运算,操作执行的速度就非常重要,这时可以使用线程对要执行的操作分段执行,这样就可以大大提高程序运行速度和性能。

weixin_45867307的博客 754

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

c#学习07-09

正是开始i学习C#语言,嘻嘻,买了本C#入门经典

264

个人C#面试题系列-更新至2022/09

C#面试题系列,单独记录一下毕业后这两年所经历的一些关于C#的面试。就当梳理一下知识。

lilizys的博客 1万+
上一篇: 08-C#
下一篇: 11-C#
似水明俊德
博客等级 码龄8年 247粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值