Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在进行put调用时使用c#线程_C#_Multithreading - Fatal编程技术网

在进行put调用时使用c#线程

在进行put调用时使用c#线程,c#,multithreading,C#,Multithreading,我不熟悉c#的线程世界。我读到有很多不同的方法可以像顺序线程一样执行线程 我的情况如下。以下哪一个更适合 我有一个复杂对象的列表。我将分别调用每个对象[放置体]的放置端点。列表中可以有1000个或更多对象。我不能一次传递所有对象,因此我必须在每次调用put端点时传递每个对象。这样,如果有1000个对象,我必须分别调用1000个 每个put调用都是相互独立的,而我必须存储来自每个调用的响应的属性 我想把线程的概念应用到上面,但不确定是哪一个,以及如何实现 如有任何建议,将不胜感激 提前感谢 根据下

我不熟悉c#的线程世界。我读到有很多不同的方法可以像顺序线程一样执行线程

我的情况如下。以下哪一个更适合

我有一个复杂对象的列表。我将分别调用每个对象[放置体]的放置端点。列表中可以有1000个或更多对象。我不能一次传递所有对象,因此我必须在每次调用put端点时传递每个对象。这样,如果有1000个对象,我必须分别调用1000个

每个put调用都是相互独立的,而我必须存储来自每个调用的响应的属性

我想把线程的概念应用到上面,但不确定是哪一个,以及如何实现

如有任何建议,将不胜感激

提前感谢

根据下面的评论, 将方法签名放在这里并添加更多细节

我有
IEnumerable
。对于每个camel,我必须进行一个put请求调用,并根据每个调用的响应更新表。我将编写一个新的方法来接受这个列表,并使用下面两个方法来调用和更新表。我必须确保,我在同一时间进行的调用不超过100次,并且我正在调用的API可以由同一用户每分钟调用100次

我们有一个方法
公共Camel SendRequest(处理程序、uri、路由、Camel)//基本上会获取所有参数并为您提供骆驼。


我们的方法是
public void updateInTable(实体骆驼)//更新表。

HTTP调用通常使用,其HTTP方法已经是异步的。您不需要创建自己的线程或任务

所有异步方法都返回
任务
任务值。您需要使用
await
关键字来等待操作异步完成-这意味着在操作完成之前释放线程。当这种情况发生时,执行将在
wait`之后恢复

您可以看到如何编写PUT请求。该示例使用该方法减少将
产品
类序列化为字符串并创建具有正确内容类型的
StringContent
类所需的样板代码,例如:

var response = await client.PutAsJsonAsync($"api/products/{product.Id}", product);
response.EnsureSuccessStatusCode();
如果您想放置1000个产品,您所需要的只是一个包含这些产品的数组或列表。您可以使用LINQ拨打多个电话,并等待他们在结束时返回的任务:

var callTasks = myProducts.Select(product=>client.PutAsJsonAsync($"api/products/{product.Id}", product);
var responses =  await Task.WhenAll(callTasks);
这意味着您必须等待所有请求完成,然后才能检查是否有任何请求成功。您可以更改
选择的主体以等待响应本身:

var callTasks = myProducts.Select(async product=>{
       var response=await client.PutAsJsonAsync($"api/products/{product.Id}", product);
       if (!response.IsSuccessStatusCode)
       {
           //Log the error                  
       }
       return response.StatusCode;
});
var responses=await Task.WhenAll(callTasks);
不过,最好将lambda转换为单独的方法,例如PutProductAsync:

async Task<HttpStatusCode> PutProduct(Product product,HttpClient client)
{
           var response=await client.PutAsJsonAsync($"api/products/{product.Id}", product);
           if (!response.IsSuccessStatusCode)
           {
               //Log the error                  
           }
           return response.StatusCode;
 };

 var callTasks = myProducts.Select(product=>PutProductAsync(product));
 var responses=await Task.WhenAll(callTasks);
异步任务产品(产品产品,HttpClient客户端)
{
var response=await client.PutAsJsonAsync($“api/products/{product.Id}”,product);
如果(!response.issucessStatusCode)
{
//记录错误
}
返回response.StatusCode;
};
var callTasks=myProducts.Select(product=>PutProductAsync(product));
var responses=wait Task.WhenAll(callTasks);

我建议使用微软的反应式框架。你需要NuGet“System.Reactive”来获取比特

然后你可以这样做:

var urls = new string[1000]; //somehow populated;

Func<string, HttpContent, IObservable<string>> putCall = (u, c) =>
    Observable
        .Using(
            () => new HttpClient(),
            hc =>
                from resp in Observable.FromAsync(() => hc.PutAsync(u, c))
                from body in Observable.FromAsync(() => resp.Content.ReadAsStringAsync())
                select body);

var callsPerTimeSpanAllowed = 100;
var timeSpanAllowed = TimeSpan.FromMinutes(1.0);

IObservable<IList<string>> bufferedIntervaledUrls =
    Observable.Zip(
        Observable.Interval(timeSpanAllowed),
        urls.ToObservable().Buffer(callsPerTimeSpanAllowed),
        (_, buffered_urls) => buffered_urls);

var query =
    from bufferedUrls in bufferedIntervaledUrls
    from url in bufferedUrls
    from result in putCall(url, new StringContent("YOURCONTENTHERE"))
    select new { url, result };

IDisposable subscription =
    query
        .Subscribe(
            x => { /* do something with each `x.url` & `x.result` */ },
            () => { /* do something when it is all finished */ });
var url=新字符串[1000]//不知何故人口众多;
Func putCall=(u,c)=>
可观察
.使用(
()=>新的HttpClient(),
hc=>
from resp in Observable.fromsync(()=>hc.PutAsync(u,c))
from body在Observable.fromsync(()=>resp.Content.ReadAsStringAsync()中)
选择主体);
var callsPerTimeSpanAllowed=100;
var timeSpanAllowed=TimeSpan.FromMinutes(1.0);
IObservable bufferedIntervaledUrls=
可观察的(
可观察的时间间隔(允许的时间),
URL.ToObservable().Buffer(允许调用调用参数),
(缓冲的URL)=>缓冲的URL);
变量查询=
从bufferedIntervaledUrls中的BufferedUrl
从bufferedUrls中的url
来自putCall中的结果(url、新StringContent(“YOURCONTENTHERE”))
选择新的{url,result};
IDisposable订阅=
查询
.订阅(
x=>{/*对每个`x.url`&`x.result`*/}执行一些操作,
()=>{/*完成后做点什么*/});
这段代码将URL分成100个块(或缓冲区),并将它们放在相隔1分钟的时间线上(或间隔)。然后为每个URL调用
putCall
,并返回结果


现在对您来说可能有点高级,但我认为这个答案可能有助于了解它的干净程度。

首先,最早支持的.NET版本是4.5.2,其中HTTP调用是使用
HttpClient
进行的。其次,HttpClient的方法都是异步的,例如
HttpClient.PutAsync()
将在后台运行。您不需要使用线程使它们在后台运行。您甚至可以编写
myurlObjectPairs.Select(data=>client.PutAsync(data.url,data.Content)).ToArray()
并以并行方式启动所有调用。我们正在使用c#6。我错误地添加了另一个c#4。@Vicky-您添加的签名中的类型不一致。这不可能是你真正的代码。如果您需要帮助,请尽力让我们尽可能容易回答。我们需要一个。非常感谢@Panagiotis Kanavos。唯一的问题是我要调用或使用的api只允许在一分钟左右的时间内从特定Id调用100次。如果是这样的话,最好先等一段时间,再打100个电话。我说加倍只是考虑一些缓冲时间。或者还有其他更好的方法吗?谢谢@Enigmativity。我不熟悉system.reactive extension,因此我阅读了