gpt4 book ai didi

c# - C# 中的 WebRequests 是非常 CPU 密集型的。需要更好的东西

转载 作者:行者123 更新时间:2023-12-05 08:12:27 29 4
gpt4 key购买 nike

我有一个程序需要扫描网络上运行我的程序的其他设备。我想到的解决方案是调用每个 ipAddress 以查看我的程序是否正在运行。

下面的代码完全阻塞了 cpu:-

using Newtonsoft.Json;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FileWire
{
class SearchNearby
{

private bool pc_search_cancelled = false;
private SynchronizedCollection<Thread> PCSearchThreadList;
private ConcurrentDictionary<String, String> NearbyPCList;

public void NewPcFound(string s, string s1)
{
Console.WriteLine(string.Format("PC Found at: {0} PC Name: {1}", s, s1));
}

public SearchNearby()
{
startPCScan();

while (true)
{
bool isAnyAlive = false;
foreach(Thread t in PCSearchThreadList)
{
isAnyAlive |= t.IsAlive;
}
if (!isAnyAlive)
{
Console.WriteLine("Search Complete");
foreach (var a in NearbyPCList)
{
Console.WriteLine(a.Key + " ;; " + a.Value);
}
startPCScan();
}
Thread.Sleep(100);
}
}


private void startPCScan()
{
PCSearchThreadList = new SynchronizedCollection<Thread>();
NearbyPCList = new ConcurrentDictionary<String, String>();
pc_search_cancelled = false;
String add = "";
System.Net.IPAddress[] ad = System.Net.Dns.GetHostByName(System.Net.Dns.GetHostName()).AddressList;
foreach (System.Net.IPAddress ip in ad)
{
add += ip.ToString() + "\n";
}
bool connected;
if (add.Trim(' ').Length == 0)
{
connected = false;
}
else
{
connected = true;
}
if (connected)
{
try
{
String[] addresses = add.Split('\n');
foreach (String address in addresses)
{
int myIP = int.Parse(address.Substring(address.LastIndexOf(".") + 1));
for (int def = 0; def <= 10; def++)
{
int finalDef = def;

for (int j = 0; j < 10; j++)
{
string finalJ = j.ToString();
Thread thread = new Thread(new ThreadStart(() =>
{

if (!pc_search_cancelled)
{
for (int i = (finalDef * 25); i < (finalDef * 25) + 25 && i <= 255; i++)
{
if (!pc_search_cancelled)
{
if (i != myIP)
{
String callToAddress = "http://" + address.Substring(0, address.LastIndexOf(".")) + "." + i + ":" + (1234 + int.Parse(finalJ)).ToString();
String name = canGetNameAndAvatar(callToAddress);
if (name != null)
{
NearbyPCList[callToAddress] = name;
NewPcFound(callToAddress, name);
}
}
}
}
}

}));
PCSearchThreadList.Add(thread);
thread.Start();
}
}
}
} catch (Exception e) {
}
}
}
private String canGetNameAndAvatar(String connection)
{
String link = connection + "/getAvatarAndName";
link = link.Replace(" ", "%20");
try
{

var client = new HttpClient();
client.Timeout = TimeSpan.FromMilliseconds(500);
var a = new Task<HttpResponseMessage>[1];
a[0] = client.GetAsync(link);
Task.WaitAll(a);
var b = a[0].Result.Content.ReadAsStringAsync();
Task.WaitAll(b);

Console.WriteLine(b.Result);

string result = b.Result;
result = result.Substring(result.IndexOf("<body>") + 6, result.IndexOf("</body>") - (result.IndexOf("<body>") + 6));
AvtarAndName json = JsonConvert.DeserializeObject<AvtarAndName>(result);
if (json != null)
{
return json.name;
}
}
catch
{
return null;
}
return null;
}
}

}

这正是我在 Java 中使用的 Java 代码的 C# 版本:-

import com.sun.istack.internal.Nullable;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URI;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

public class PCScan {

private static boolean pc_search_cancelled = false;
private static List<Thread> PCSearchThreadList;
private static HashMapWithListener<String, String> NearbyPCList;
public static void main(String[] args) {

start();

while (true) {
int numCompleted = 0;
for (Thread t : PCSearchThreadList) {
if (!t.isAlive()) {
numCompleted++;
}
}
if (numCompleted == PCSearchThreadList.size()) {
start();
}
}
}

private static void start() {

try {
startPCScan();
} catch (SocketException e) {
e.printStackTrace();
}

NearbyPCList.setPutListener(new HashMapWithListener.putListener() {
@Override
public void onPut(Object key, Object value) {
System.out.println(key.toString() + ";;" + value.toString());
}
});
}

private static void startPCScan() throws SocketException {
pc_search_cancelled = false;
PCSearchThreadList = new CopyOnWriteArrayList<>();
NearbyPCList = new HashMapWithListener<>();
Enumeration<NetworkInterface> enumeration = NetworkInterface.getNetworkInterfaces();
boolean connected;
String add = "";
while (enumeration.hasMoreElements()) {
NetworkInterface interfacea = enumeration.nextElement();
if (!interfacea.isLoopback()) {
Enumeration<InetAddress> enumeration1 = interfacea.getInetAddresses();

while (enumeration1.hasMoreElements()) {
String address = enumeration1.nextElement().getHostAddress();
if (address.split("\\.").length == 4) {
add += address + "\n";
}
}
}

}

System.out.println(add);
connected = true;
if (connected) {
try {
String[] addresses = add.split("\n");
addresses = new HashSet<String>(Arrays.asList(addresses)).toArray(new String[0]);
for (String address : addresses) {
int myIP = Integer.parseInt(address.substring(address.lastIndexOf(".") + 1));
for (int def = 0; def <= 10; def++) {
int finalDef = def;

for (int j = 0; j < 10; j++) {
int finalJ = j;
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
if (!pc_search_cancelled) {
for (int i = (finalDef * 25); i < (finalDef * 25) + 25 && i <= 255; i++) {
if (!pc_search_cancelled) {
if (i != myIP) {
String callToAddress = "http://" + address.substring(0, address.lastIndexOf(".")) + "." + i + ":" + String.valueOf(Integer.parseInt("1234") + finalJ);
String name = canGetNameAndAvatar(callToAddress);
if (name != null) {
NearbyPCList.put(callToAddress, name);
}
}
}
}
}
}
});
PCSearchThreadList.add(thread);
thread.start();
}
}
// }
// }).start();
}
} catch (Exception e) {
}
}
}
private static String canGetNameAndAvatar(String connection) {
String link = connection + "/getAvatarAndName";
link = link.replaceAll(" ", "%20");
try {
HttpClient client = new DefaultHttpClient();
HttpParams httpParams = client.getParams();
httpParams.setParameter(
CoreConnectionPNames.CONNECTION_TIMEOUT, 500);
HttpGet request = new HttpGet();
request.setURI(new URI(link));
HttpResponse response = client.execute(request);
BufferedReader in = new BufferedReader(new
InputStreamReader(response.getEntity().getContent()));

StringBuffer sb = new StringBuffer("");
String line="";

while ((line = in.readLine()) != null) {
sb.append(line);
break;
}
in.close();
String result = sb.toString();
result = result.substring(result.indexOf("<body>") + 6, result.indexOf("</body>"));
JSONObject json = new JSONObject(result);
if (json != null) {
return json.getString("name");
}
}
catch (Exception ignored){
return null;
}
return null;
}
static class HashMapWithListener<K, V> extends HashMap<K, V> {

private putListener PutListener;
public void setPutListener(putListener PutListener) {
this.PutListener = PutListener;
}

@Nullable
@Override
public V put(K key, V value) {
PutListener.onPut(key, value);
return super.put(key, value);
}

interface putListener {
public void onPut(Object key, Object value);
}

}

}

Java 代码运行得非常好,只使用了大约 20% 的 CPU,而 C# 代码绝对锁定了 PC。我尝试了 Webclient、webrequest、httpClient。所有这些都具有完全相同的性能。

我需要代码在 c# 中,因为我不能在我的程序中包含整个 JRE,因为它太大了。我的程序和 GUI 的其余部分采用 WPF 格式。

此外,我需要代码在扫描端口 1234-1243 时最多花费 50 秒。即使在中端安卓手机上,这段代码也能正常工作。所以,我不知道问题出在哪里。

最佳答案

我会建议这样的事情(为了举例,我已经简化了它):

private static HttpClient _client = new HttpClient() { Timeout = TimeSpan.FromMilliseconds(500) };

private async Task<Something> GetSomething(string url)
{
using (HttpResponseMessage response = await _client.GetAsync(url))
{
string json = await response.ReadAsStringAsync();
return JsonConvert.DeserializeObject<Something>(json);
}
}

private async Task<Something[]> GetSomethings(string[] urls)
{
IEnumerable<Task<Something>> requestTasks = urls.Select(u => GetSomething(u));
Something[] results = await Task.WhenAll<Something>(requestTasks);
return results;
}

您还应该使调用 GetSomethings 的方法异步,并等待它,并在调用链中一直执行相同的操作。

async/await使用线程池来执行,在请求的IO部分发生时线程实际上是挂起的,也就是说这期间没有占用CPU时间。当 IO 部分完成后,它会在 await 恢复代码。

相关信息:

关于c# - C# 中的 WebRequests 是非常 CPU 密集型的。需要更好的东西,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68149341/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com