C# 与lambda一起使用时,等待操作员发出问题
我有2个实体,我想将一些数据从第二个实体复制到第一个实体,然后我想返回一个简单的字符串,表示成功。我正在使用Polly发出http请求。我计划获取json格式的数据,然后在我的实体模型中进行转换,并执行我能够执行的操作,但同时调用返回的任务不同类型的数据模型可能略有不同,但会产生一些错误。我不太擅长多线程方法C# 与lambda一起使用时,等待操作员发出问题,c#,multithreading,task,C#,Multithreading,Task,我有2个实体,我想将一些数据从第二个实体复制到第一个实体,然后我想返回一个简单的字符串,表示成功。我正在使用Polly发出http请求。我计划获取json格式的数据,然后在我的实体模型中进行转换,并执行我能够执行的操作,但同时调用返回的任务不同类型的数据模型可能略有不同,但会产生一些错误。我不太擅长多线程方法 public interface IMyRepository { string ValidateData(MyData myData); } public class MyR
public interface IMyRepository
{
string ValidateData(MyData myData);
}
public class MyRepository :IMyRepository
{ private readonly RetryPolicy<HttpResponseMessage> _httpRequestPolicy;
public MyRepository()
{
_httpRequestPolicy = Policy.HandleResult<HttpResponseMessage>(
r => r.StatusCode == HttpStatusCode.InternalServerError)
.WaitAndRetryAsync(3,
retryAttempt => TimeSpan.FromSeconds(retryAttempt), (exception, timeSpan, retryCount, context1) =>
{
var msg = $"Retry {retryCount} implemented with Pollys RetryPolicy " +
$"of {context1.PolicyKey} " +
$"at {context1.ExecutionKey}, " +
$"due to: {exception}.";
});
}
public string ValidateData(MyData MyData)
{
var MyDataOne= Task<MyData>.Factory.StartNew(() => await MyRepository.getProfileOne());
var MyDataTwo= Task<MyData>.Factory.StartNew(() => await MyRepository.getProfileTwo());
//Update some property of MyDataOne on basis of MyDataTwo and return true or fasle in variable **result**
return result;
}
public static async Task<InsuranceCompanyData> getCusomerProfile()
{
var httpClient = GetHttpClient();
string requestEndpoint = "numbers/Get";
HttpResponseMessage httpResponse = await _httpRequestPolicy.ExecuteAsync(() => httpClient.GetAsync(requestEndpoint));
IEnumerable<int> numbers = await httpResponse.Content.ReadAsAsync<IEnumerable<int>>();
return new InsuranceCompanyData();
}
private static HttpClient GetHttpClient()
{
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(@"http://localhost:2351/api/");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return httpClient;
}
}
public static async Task<MyData> getProfileOne()
{
var httpClient = GetHttpClient();
string requestEndpoint = "/numbers/Get1";
HttpResponseMessage httpResponse = await _httpRequestPolicy.ExecuteAsync(() => httpClient.GetAsync(requestEndpoint));
// IEnumerable<string> data1= await httpResponse.Content.ReadAsAsync<IEnumerable<string>>();
return new MyData();
}
public static async Task<MyData> getProfileTwo()
{
var httpClient = GetHttpClient();
string requestEndpoint = "/numbers/Get2";
HttpResponseMessage httpResponse = await _httpRequestPolicy.ExecuteAsync(() => httpClient.GetAsync(requestEndpoint));
// IEnumerable<string> data2= await httpResponse.Content.ReadAsAsync<IEnumerable<string>>();
return new MyyData();
}
private static HttpClient GetHttpClient()
{
var httpClient = new HttpClient();
httpClient.BaseAddress = new Uri(@"http://localhost:2351/api/");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
return httpClient;
}
我发现以下错误:
“await”运算符只能在异步lambda表达式中使用。考虑用“AsiNC”修饰符标记lambda表达式。
及
非静态字段、方法或属性“MyRepository.”需要对象引用。\u httpRequestPolicy'
不要使用Task.Factory.StartNew(不推荐使用,也不支持异步lambda,您甚至不需要它),而是使用Task.Run:
请注意,我更改了变量名以反映它们的实际情况。这些任务在某种程度上可能会产生结果。它们不是这些行动的结果
对于第二个问题,您将_httpRequestPolicy声明为实例成员,而您本应将其声明为静态成员,以便它在没有实例的情况下可用。不过,正如在注释中所讨论的,您可以将getProfileOne和getProfileTwo作为实例方法 为什么不更改ValidateData签名并向方法添加async关键字
public async Task<string> ValidateDataAsync(MyData MyData)
{
var task1 = Task<MyData>.Factory.StartNew(() => MyRepository.getProfileOne());
var task2 = Task<MyData>.Factory.StartNew(() => MyRepository.getProfileTwo());
await Task.WhenAll(task1, task2)
//Update some property of MyDataOne on basis of MyDataTwo and return true or fasle in variable **result**
return result;
}
正如@Camilo Terevinto所说,最好使用Task.Run而不是TaskFactory.StartNew
你为什么打电话给Task.Factory.StartNew?只需调用这两个方法并记住它们返回的任务,然后等待这两个任务。我希望它们是独立和异步的,所以我调用了Task.Factory.StartNew.抱歉,但我不理解您的建议。如果我不编写Task.Factory.StartNew并编写var InsuranceCompanyData=wait InsuranceCompanyRepository.getCusomerProfile;我得到错误CS4032“wait”运算符只能在异步方法中使用。考虑用“异步”修饰符标记这个方法,并将它的返回类型改为“任务”。你试图在这里混合同步和异步,只要坚持一个就不会看到这些问题。如果它们是异步方法,就不需要显式地启动新任务。如果它们不是完全异步的,我想改为让它们异步。@DaisyShipton-我不明白方法不是异步的。有指针吗?我不能让它成为\u httpRequestPolicy静态的,因为我需要在构造函数`\u httpRequestPolicy=Policy.HandlerResult r=>r.StatusCode==HttpStatusCode.InternalServerError`中初始化它,我将按照您的建议进行更改。非常感谢。@PoojaMalik如果您可以编辑您的问题并添加导致该问题的代码,我将更新我的答案以显示如何修改it@PoojaMalik我明白了,但除非您需要为MyRepository的每个实例提供一个新的_httpRequestPolicy实例,您可以将其设置为静态,并在InlineHanks中为您的评论分配它,但我无法理解。我需要polly处理每个实例,以便它可以重试每个实例,并确保其具有弹性。如果我无法正确理解,请进行相应的处理。此外,在线分配你是指静态构造函数还是银行,但我不能更改'ValidateData',因为我不想更改现有接口。你可以将其更改为Task.WhenAll.GetAwaiter.GetResult而不必等待
public async Task<string> ValidateDataAsync(MyData MyData)
{
var task1 = Task<MyData>.Factory.StartNew(() => MyRepository.getProfileOne());
var task2 = Task<MyData>.Factory.StartNew(() => MyRepository.getProfileTwo());
await Task.WhenAll(task1, task2)
//Update some property of MyDataOne on basis of MyDataTwo and return true or fasle in variable **result**
return result;
}