c#并行请求,且考虑并发问题

做个干净的年轻人 2018-07-03 02:18:05
需求描述:

酒店列表业务中,我们要根据自身业务中的查询条件分别请求艺龙,去哪,携程N家供应商的数据,比方各个供应商都是1秒返回数据。那么我拿到数据需要3秒,拿到数据后在清洗,合并,可能需要4-5秒的时间才能吐给前端

想要实现:
艺龙,携程,去哪N个供应商多线程并行请求,以最慢的那个供应商的响应结果为我得到数据的时间,在上述需求为例,最终我拿到N家供应商的数据时间为1秒,那么清洗,合并总共3-4秒,这样的话就节省了2-3秒的时间

备注:集成环境尝试过,但是会出现并发问题,比方同一秒多个人同时,不同条件刷新查询,A,B,C拿到的数据会错乱,即:A拿到了自己查询的上海的数据,也拿到了B查询的北京的数据。

最后:希望有类似业务的大牛帮忙写个demo,甚是捉鸡,新人也没啥分,但是心意是满满的,在此感谢了。本人QQ:250374660希望指点一二
...全文
1154 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
richiejen_555 2018-07-05
  • 打赏
  • 举报
回复
谢谢分享 谢谢
qq_42591983 2018-07-05
  • 打赏
  • 举报
回复
Parallel
xiaoxiangqing 2018-07-05
  • 打赏
  • 举报
回复
用Parallel这个,最简单
  • 打赏
  • 举报
回复
引用 34 楼 qq_22265371 的回复:

前面的不管了,就看这楼的代码,能不能实现我的需求。
或者谁用更好的,直接改改我的代码,贴上来,感激不尽!



namespace Tasks
{
/// <summary>
/// c#多线程并行demo
/// </summary>
class Program
{
static void Main(string[] args)
{

var queryid = "123456789";
var result = QueryHotels(new QueryHotelParameter { ArrivalDate = "2018-07-04", CityCode = "123", DepartureDate = "2018-07-05" }, queryid);
var hotels = result.Select(item => item.Value).ToList();
//hotels 里面是去哪,艺龙 每个供应商返回的数据合并集,共两条数据

}
private static IEnumerable<KeyValuePair<string, Hotel>> QueryHotels(QueryHotelParameter parameter, string qweryId)
{
var lstHotels = new List<KeyValuePair<string, Hotel>>();
Parallel.Invoke(
() => lstHotels.Add(QueryQuNarHotels(parameter, qweryId)),
() => lstHotels.Add(QueryElongHotels(parameter, qweryId))
);
Task.WaitAll();
return lstHotels;
}


/// <summary>
/// 获取去哪酒店
/// </summary>
/// <param name="parameter"></param>
/// <param name="queryId"></param>
private static KeyValuePair<string, Hotel> QueryQuNarHotels(QueryHotelParameter parameter, string queryId)
{
var result = new KeyValuePair<string, Hotel>(queryId, new Hotel { Name = "去哪的酒店", Price = 100 });
return result;
}

/// <summary>
/// 获取艺龙酒店
/// </summary>
/// <param name="parameter"></param>
/// <param name="queryId"></param>
private static KeyValuePair<string, Hotel> QueryElongHotels(QueryHotelParameter parameter, string queryId)
{
var result = new KeyValuePair<string, Hotel>(queryId, new Hotel { Name = "艺龙的酒店", Price = 100 });
return result;
}


public class Hotel
{
public string Name { set; get; }

public decimal Price { set; get; }

}

public class QueryHotelParameter
{
public string CityCode { set; get; }

public string ArrivalDate { set; get; }

public string DepartureDate { set; get; }

}

}
}

22楼都给你写好了。。。。
SoulRed 2018-07-05
  • 打赏
  • 举报
回复
建议用orleans 。如果你有时间的话
  • 打赏
  • 举报
回复
引用 24 楼 qq_22265371 的回复:
[quote=引用 23 楼 starfd 的回复:]
Parallel并不会出现你所谓的错乱问题,所以问题在于你的查询方法到底是怎么写的,如果只是根据url去请求并返回结果,不可能存在url是a,结果返回b的情况
然后看了你18楼的代码,这写法不对,应该是每个each对应某个请求,而不是在一个请求里去将所有地址都访问一遍
Parallel.For(0, 2, i => { 
switch(i)
{
case 0://艺龙
break;
case 1://携程
break;
}
//将获取结果添加到result
});



大哥看看22楼的方法 可否实现我的业务?[/quote]
他对你的实际需求理解都错了,你还要他看。
你想做的是一个用户来你这里你去查询多个端口,然后处理数据统一返回给用户。
他理解的是你要查询多个端口,然后处理,并没有想到要对应到每个用户头上的问题,他那样做出来是携程的和艺龙的分开返回的你确定让他看是对的?
  • 打赏
  • 举报
回复
引用 23 楼 starfd 的回复:
Parallel并不会出现你所谓的错乱问题,所以问题在于你的查询方法到底是怎么写的,如果只是根据url去请求并返回结果,不可能存在url是a,结果返回b的情况
然后看了你18楼的代码,这写法不对,应该是每个each对应某个请求,而不是在一个请求里去将所有地址都访问一遍
Parallel.For(0, 2, i => { 
switch(i)
{
case 0://艺龙
break;
case 1://携程
break;
}
//将获取结果添加到result
});



大哥看看22楼的方法 可否实现我的业务?
  • 打赏
  • 举报
回复
Parallel并不会出现你所谓的错乱问题,所以问题在于你的查询方法到底是怎么写的,如果只是根据url去请求并返回结果,不可能存在url是a,结果返回b的情况
然后看了你18楼的代码,这写法不对,应该是每个each对应某个请求,而不是在一个请求里去将所有地址都访问一遍
Parallel.For(0, 2, i => { 
switch(i)
{
case 0://艺龙
break;
case 1://携程
break;
}
//将获取结果添加到result
});
  • 打赏
  • 举报
回复
修改了一下原有的操作公共变量为返回后操作,在本机测试没有增加处理时间。

using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Tasks
{
/// <summary>
/// c#多线程并行demo
/// </summary>
class Program
{

private static BlockingCollection<System.Collections.Generic.KeyValuePair<string, Hotel>> hotels = new BlockingCollection<System.Collections.Generic.KeyValuePair<string, Hotel>>();
static void Main(string[] args)
{

var stopwatch = new Stopwatch();
stopwatch.Start();
Parallel.For(0, 10, (x) => {
string queryId = x.ToString();
System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>> lstHotels
= QueryHotels(new QueryHotelParameter(), queryId);
foreach (System.Collections.Generic.KeyValuePair<string, Hotel> item in lstHotels)
{
hotels.Add(item);
}
});
foreach (var hotel in hotels)
{
Console.WriteLine(string.Format("第{0}次查询,查询结果为{1}",hotel.Key,hotel.Value.Name));
}
Console.WriteLine("并行耗时:" + stopwatch.Elapsed.TotalSeconds);
Console.ReadLine();

}


private static System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>> QueryHotels(QueryHotelParameter parameter,string QweryId)
{
System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>> lstHotels = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>>();
Parallel.Invoke(
() => lstHotels.Add(QueryQuNarHotels(parameter, QweryId)),
() => lstHotels.Add(QueryElongHotels(parameter, QweryId))
);
Task.WaitAll();
return lstHotels;
}
/// <summary>
/// 获取去哪酒店
/// </summary>
/// <param name="parameter"></param>
private static System.Collections.Generic.KeyValuePair<string, Hotel> QueryQuNarHotels(QueryHotelParameter parameter, string QueryId)
{
System.Collections.Generic.KeyValuePair<string, Hotel> result = new System.Collections.Generic.KeyValuePair<string, Hotel>(QueryId, new Hotel { Name = "去哪的酒店", Price = 100 });
Thread.Sleep(1000);
return result;
}
/// <summary>
/// 获取艺龙酒店
/// </summary>
/// <param name="parameter"></param>
private static System.Collections.Generic.KeyValuePair<string, Hotel> QueryElongHotels(QueryHotelParameter parameter, string QueryId)
{
System.Collections.Generic.KeyValuePair<string, Hotel> result = new System.Collections.Generic.KeyValuePair<string, Hotel>(QueryId, new Hotel { Name = "艺龙的酒店", Price = 100 });
Thread.Sleep(1000);
return result;
}


public class Hotel
{

public string Name { set; get; }

public decimal Price { set; get; }

}

public class QueryHotelParameter
{

public string CityCode { set; get; }

public string ArrivalDate { set; get; }

public string DepartureDate { set; get; }

}

}
}

  • 打赏
  • 举报
回复
引用 20 楼 qq_22265371 的回复:
写了个demo贴上代码大家看看指点指点,这样写能不能达到我的目的



using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Tasks
{
/// <summary>
/// c#多线程并行demo
/// </summary>
class Program
{

private static BlockingCollection<Hotel> hotels = new BlockingCollection<Hotel>();
static void Main(string[] args)
{

var stopwatch = new Stopwatch();
stopwatch.Start();
QueryHotels(null);
foreach (var hotel in hotels)
{
Console.WriteLine(hotel.Name);
}
Console.WriteLine("并行耗时:" + stopwatch.Elapsed.TotalSeconds);
Console.ReadLine();

}


public static void QueryHotels(QueryHotelParameter parameter)
{
Parallel.Invoke(
() => QueryQuNarHotels(parameter),
() => QueryElongHotels(parameter)
);
Task.WaitAll();
}
/// <summary>
/// 获取去哪酒店
/// </summary>
/// <param name="parameter"></param>
public static void QueryQuNarHotels(QueryHotelParameter parameter)
{
hotels.Add(new Hotel { Name = "去哪的酒店", Price = 100 });
Thread.Sleep(1000);
}
/// <summary>
/// 获取艺龙酒店
/// </summary>
/// <param name="parameter"></param>
public static void QueryElongHotels(QueryHotelParameter parameter)
{
hotels.Add(new Hotel { Name = "艺龙的酒店", Price = 100 });
Thread.Sleep(1000);
}


public class Hotel
{

public string Name { set; get; }

public decimal Price { set; get; }

}

public class QueryHotelParameter
{

public string CityCode { set; get; }

public string ArrivalDate { set; get; }

public string DepartureDate { set; get; }

}

}
}



using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Tasks
{
/// <summary>
/// c#多线程并行demo
/// </summary>
class Program
{

private static BlockingCollection<System.Collections.Generic.KeyValuePair<string, Hotel>> hotels = new BlockingCollection<System.Collections.Generic.KeyValuePair<string, Hotel>>();
static void Main(string[] args)
{

var stopwatch = new Stopwatch();
stopwatch.Start();
Parallel.For(0, 10, (x) => {
string queryId = x.ToString();
QueryHotels(null, queryId);
});
foreach (var hotel in hotels)
{
Console.WriteLine(string.Format("第{0}次查询,查询结果为{1}",hotel.Key,hotel.Value.Name));
}
Console.WriteLine("并行耗时:" + stopwatch.Elapsed.TotalSeconds);
Console.ReadLine();

}


private static void QueryHotels(QueryHotelParameter parameter,string QweryId)
{
System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>> lstHotels = new System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>>();
Parallel.Invoke(
() => lstHotels.Add(QueryQuNarHotels(parameter, QweryId)),
() => lstHotels.Add(QueryElongHotels(parameter, QweryId))
);
Task.WaitAll();
foreach (System.Collections.Generic.KeyValuePair<string, Hotel> item in lstHotels)
{
hotels.Add(item);
}
}
/// <summary>
/// 获取去哪酒店
/// </summary>
/// <param name="parameter"></param>
private static System.Collections.Generic.KeyValuePair<string, Hotel> QueryQuNarHotels(QueryHotelParameter parameter, string QueryId)
{
System.Collections.Generic.KeyValuePair<string, Hotel> result = new System.Collections.Generic.KeyValuePair<string, Hotel>(QueryId, new Hotel { Name = "去哪的酒店", Price = 100 });
Thread.Sleep(1000);
return result;
}
/// <summary>
/// 获取艺龙酒店
/// </summary>
/// <param name="parameter"></param>
private static System.Collections.Generic.KeyValuePair<string, Hotel> QueryElongHotels(QueryHotelParameter parameter, string QueryId)
{
System.Collections.Generic.KeyValuePair<string, Hotel> result = new System.Collections.Generic.KeyValuePair<string, Hotel>(QueryId, new Hotel { Name = "艺龙的酒店", Price = 100 });
Thread.Sleep(1000);
return result;
}


public class Hotel
{

public string Name { set; get; }

public decimal Price { set; get; }

}

public class QueryHotelParameter
{

public string CityCode { set; get; }

public string ArrivalDate { set; get; }

public string DepartureDate { set; get; }

}

}
}



稍微修改了一下,加了防止多次查询不知道谁是谁的处理。
  • 打赏
  • 举报
回复
写了个demo贴上代码大家看看指点指点,这样写能不能达到我的目的



using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;

namespace Tasks
{
/// <summary>
/// c#多线程并行demo
/// </summary>
class Program
{

private static BlockingCollection<Hotel> hotels = new BlockingCollection<Hotel>();
static void Main(string[] args)
{

var stopwatch = new Stopwatch();
stopwatch.Start();
QueryHotels(null);
foreach (var hotel in hotels)
{
Console.WriteLine(hotel.Name);
}
Console.WriteLine("并行耗时:" + stopwatch.Elapsed.TotalSeconds);
Console.ReadLine();

}


public static void QueryHotels(QueryHotelParameter parameter)
{
Parallel.Invoke(
() => QueryQuNarHotels(parameter),
() => QueryElongHotels(parameter)
);
Task.WaitAll();
}
/// <summary>
/// 获取去哪酒店
/// </summary>
/// <param name="parameter"></param>
public static void QueryQuNarHotels(QueryHotelParameter parameter)
{
hotels.Add(new Hotel { Name = "去哪的酒店", Price = 100 });
Thread.Sleep(1000);
}
/// <summary>
/// 获取艺龙酒店
/// </summary>
/// <param name="parameter"></param>
public static void QueryElongHotels(QueryHotelParameter parameter)
{
hotels.Add(new Hotel { Name = "艺龙的酒店", Price = 100 });
Thread.Sleep(1000);
}


public class Hotel
{

public string Name { set; get; }

public decimal Price { set; get; }

}

public class QueryHotelParameter
{

public string CityCode { set; get; }

public string ArrivalDate { set; get; }

public string DepartureDate { set; get; }

}

}
}


稻穗1989 2018-07-04
  • 打赏
  • 举报
回复
var result = new List<Hotel>();
Parallel.For(0, 2, i => {
switch(i)
{
case 0://艺龙
result.AddRange(QueryElongHotels(parameter));
break;
case 1://携程
result.AddRange(QueryQuNarHotels(parameter));
break;
}
});
return result;
  • 打赏
  • 举报
回复

前面的不管了,就看这楼的代码,能不能实现我的需求。
或者谁用更好的,直接改改我的代码,贴上来,感激不尽!



namespace Tasks
{
/// <summary>
/// c#多线程并行demo
/// </summary>
class Program
{
static void Main(string[] args)
{

var queryid = "123456789";
var result = QueryHotels(new QueryHotelParameter { ArrivalDate = "2018-07-04", CityCode = "123", DepartureDate = "2018-07-05" }, queryid);
var hotels = result.Select(item => item.Value).ToList();
//hotels 里面是去哪,艺龙 每个供应商返回的数据合并集,共两条数据

}
private static IEnumerable<KeyValuePair<string, Hotel>> QueryHotels(QueryHotelParameter parameter, string qweryId)
{
var lstHotels = new List<KeyValuePair<string, Hotel>>();
Parallel.Invoke(
() => lstHotels.Add(QueryQuNarHotels(parameter, qweryId)),
() => lstHotels.Add(QueryElongHotels(parameter, qweryId))
);
Task.WaitAll();
return lstHotels;
}


/// <summary>
/// 获取去哪酒店
/// </summary>
/// <param name="parameter"></param>
/// <param name="queryId"></param>
private static KeyValuePair<string, Hotel> QueryQuNarHotels(QueryHotelParameter parameter, string queryId)
{
var result = new KeyValuePair<string, Hotel>(queryId, new Hotel { Name = "去哪的酒店", Price = 100 });
return result;
}

/// <summary>
/// 获取艺龙酒店
/// </summary>
/// <param name="parameter"></param>
/// <param name="queryId"></param>
private static KeyValuePair<string, Hotel> QueryElongHotels(QueryHotelParameter parameter, string queryId)
{
var result = new KeyValuePair<string, Hotel>(queryId, new Hotel { Name = "艺龙的酒店", Price = 100 });
return result;
}


public class Hotel
{
public string Name { set; get; }

public decimal Price { set; get; }

}

public class QueryHotelParameter
{
public string CityCode { set; get; }

public string ArrivalDate { set; get; }

public string DepartureDate { set; get; }

}

}
}
wanghui0380 2018-07-04
  • 打赏
  • 举报
回复
Task<int>[] tasks=new Task<int>[]{add(2),add(1),add(3)};
int[] res= Task.WhenAll(tasks).Result;

其实也成,当然我这里都是忽略异常处理的写法
wanghui0380 2018-07-04
  • 打赏
  • 举报
回复
当然如果直接使用平行也可以,不过要比plinq麻烦点

Parallel.ForEach 其实有重载,不过比较麻烦,我可以给你百度一个例子

https://www.cnblogs.com/x-poior/p/6263161.html?utm_source=itdadao&utm_medium=referral

看其中的场景五,那个重载就是----采用变量临时保存,不过相比plinq就麻烦的多了
  • 打赏
  • 举报
回复
引用 29 楼 xomix 的回复:
[quote=引用 27 楼 qq_22265371 的回复:]
帮忙针对18楼的代码 写个demo可否?

前端发起一个请求,要查询上海的,2018-07-04 到 2018-07-05 的酒店,对用户来说场景就那么简单
但是到了后端,因为我们对接了很对供应商,每个供应商都可以提供 “ 上海的,2018-07-04 到 2018-07-05 的酒店 ”
所以我要根据这3个条件,并行去各个供应商把数据拿回来,比方就2个供应商,艺龙,去哪,每个请求返回10条数据,那我我就会拿到20条数据,我在根据一些规则,去重,最终可能会吐给前端15条数据。流程就是这样,我就是想后端能并行去请求,节省的我和前端的响应时间。



Parallel.For(0, 10, (x) => {
string queryId = x.ToString();
System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>> lstHotels
= QueryHotels(new QueryHotelParameter(), queryId);
foreach (System.Collections.Generic.KeyValuePair<string, Hotel> item in lstHotels)
{
hotels.Add(item);
}
});

这段不就是并发吗?你根据自己的业务需求在需要的时候调用

string queryId = "实际id";
System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>> lstHotels
= QueryHotels(new QueryHotelParameter(), queryId);
foreach (System.Collections.Generic.KeyValuePair<string, Hotel> item in lstHotels)
{
//实际处理或插入静态类
}

不就完成工作了吗?

看你自己18楼的代码精简的挺好的怎么写着写着又绕圈了。[/quote]

我已经蒙圈了 楼层有点多了~~
wanghui0380 2018-07-04
  • 打赏
  • 举报
回复
无需过于麻烦,简单就好,我们可以直接plinq,下面是例子
  class Program
{
static void Main(string[] args)
{

Task<int>[] tasks=new Task<int>[]{add(2),add(1),add(3)};
var sum = tasks.AsParallel().Sum(p => p.Result); //我们可以直接plinq
var lst= tasks.AsParallel().OrderBy(p => p.Result);
foreach (Task<int> task in lst)
{
Console.WriteLine($"排序{task.Result}");
}
Console.WriteLine($"累加计算结果:{sum}");
Console.ReadKey();
}

private static Random rand = new Random(DateTime.Now.Millisecond);
static async Task<int> add(int a)
{
//我来模拟你异步耗时访问,随机消耗点时间
await Task.Delay(TimeSpan.FromSeconds(rand.Next(0, 10)));
Console.WriteLine($"生成顺序{a}");
return a;
}


当然我这里故意忽略了异常处理,只是展示如何在plinq下进行结果聚合计算
  • 打赏
  • 举报
回复
引用 27 楼 qq_22265371 的回复:
帮忙针对18楼的代码 写个demo可否?

前端发起一个请求,要查询上海的,2018-07-04 到 2018-07-05 的酒店,对用户来说场景就那么简单
但是到了后端,因为我们对接了很对供应商,每个供应商都可以提供 “ 上海的,2018-07-04 到 2018-07-05 的酒店 ”
所以我要根据这3个条件,并行去各个供应商把数据拿回来,比方就2个供应商,艺龙,去哪,每个请求返回10条数据,那我我就会拿到20条数据,我在根据一些规则,去重,最终可能会吐给前端15条数据。流程就是这样,我就是想后端能并行去请求,节省的我和前端的响应时间。



Parallel.For(0, 10, (x) => {
string queryId = x.ToString();
System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>> lstHotels
= QueryHotels(new QueryHotelParameter(), queryId);
foreach (System.Collections.Generic.KeyValuePair<string, Hotel> item in lstHotels)
{
hotels.Add(item);
}
});

这段不就是并发吗?你根据自己的业务需求在需要的时候调用

string queryId = "实际id";
System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<string, Hotel>> lstHotels
= QueryHotels(new QueryHotelParameter(), queryId);
foreach (System.Collections.Generic.KeyValuePair<string, Hotel> item in lstHotels)
{
//实际处理或插入静态类
}

不就完成工作了吗?

看你自己18楼的代码精简的挺好的怎么写着写着又绕圈了。
  • 打赏
  • 举报
回复

var result = new List<Hotel>();
Parallel.For(0, 2, i => {
switch(i)
{
case 0://艺龙
result.AddRange(QueryElongHotels(parameter));
break;
case 1://携程
result.AddRange(QueryQuNarHotels(parameter));
break;
}
});
return result;
  • 打赏
  • 举报
回复
引用 25 楼 xomix 的回复:
[quote=引用 24 楼 qq_22265371 的回复:]
[quote=引用 23 楼 starfd 的回复:]
Parallel并不会出现你所谓的错乱问题,所以问题在于你的查询方法到底是怎么写的,如果只是根据url去请求并返回结果,不可能存在url是a,结果返回b的情况
然后看了你18楼的代码,这写法不对,应该是每个each对应某个请求,而不是在一个请求里去将所有地址都访问一遍
Parallel.For(0, 2, i => { 
switch(i)
{
case 0://艺龙
break;
case 1://携程
break;
}
//将获取结果添加到result
});



大哥看看22楼的方法 可否实现我的业务?[/quote]
他对你的实际需求理解都错了,你还要他看。
你想做的是一个用户来你这里你去查询多个端口,然后处理数据统一返回给用户。
他理解的是你要查询多个端口,然后处理,并没有想到要对应到每个用户头上的问题,他那样做出来是携程的和艺龙的分开返回的你确定让他看是对的?[/quote]


帮忙针对18楼的代码 写个demo可否?

前端发起一个请求,要查询上海的,2018-07-04 到 2018-07-05 的酒店,对用户来说场景就那么简单
但是到了后端,因为我们对接了很对供应商,每个供应商都可以提供 “ 上海的,2018-07-04 到 2018-07-05 的酒店 ”
所以我要根据这3个条件,并行去各个供应商把数据拿回来,比方就2个供应商,艺龙,去哪,每个请求返回10条数据,那我我就会拿到20条数据,我在根据一些规则,去重,最终可能会吐给前端15条数据。流程就是这样,我就是想后端能并行去请求,节省的我和前端的响应时间。



加载更多回复(20)

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧