나는이 async
방법을 :
public async Task<string> GenerateCodeAsync()
{
string code = await GenerateCodeService.GenerateCodeAsync();
return code;
}
이 메소드를 동기 메소드에서 호출해야합니다.
GenerateCodeAsync
이것이 동 기적으로 작동하기 위해 메소드 를 복제하지 않고 어떻게 할 수 있습니까?
최신 정보
그러나 합리적인 해결책을 찾지 못했습니다.
그러나 HttpClient
이미이 패턴을 구현하고 있음을 알았습니다.
using (HttpClient client = new HttpClient())
{
// async
HttpResponseMessage responseAsync = await client.GetAsync(url);
// sync
HttpResponseMessage responseSync = client.GetAsync(url).Result;
}
답변
Result
작업 의 속성에 액세스 할 수 있으며 결과를 사용할 수있을 때까지 스레드가 차단됩니다.
string code = GenerateCodeAsync().Result;
참고 : 경우에 따라 교착 상태가 발생할 수 있습니다 Result
. 메인 스레드를 차단하면 나머지 비동기 코드가 실행되지 않습니다. 이런 일이 발생하지 않도록하려면 다음과 같은 옵션이 있습니다.
.ConfigureAwait(false)
라이브러리 방법에 추가 하거나-
스레드 풀 스레드에서 비동기 메소드를 명시 적으로 실행하고 완료 될 때까지 기다리십시오.
string code = Task.Run(GenerateCodeAsync).Result;
이것은 하지 않습니다 그냥 아무 생각없이 추가해야한다는 것을 의미 .ConfigureAwait(false)
모든 비동기 호출 후! 사용시기 및시기에 대한 자세한 분석 .ConfigureAwait(false)
은 다음 블로그 게시물을 참조하십시오.
답변
대기자 ( GetAwaiter()
)를 확보하고 비동기 타스크 ( GetResult()
) 의 완료 대기를 종료해야합니다 .
string code = GenerateCodeAsync().GetAwaiter().GetResult();
답변
델리게이트, 람다 표현을 사용 하여이 작업을 수행 할 수 있어야합니다
private void button2_Click(object sender, EventArgs e)
{
label1.Text = "waiting....";
Task<string> sCode = Task.Run(async () =>
{
string msg =await GenerateCodeAsync();
return msg;
});
label1.Text += sCode.Result;
}
private Task<string> GenerateCodeAsync()
{
return Task.Run<string>(() => GenerateCode());
}
private string GenerateCode()
{
Thread.Sleep(2000);
return "I m back" ;
}
답변
이 메소드를 동기식 메소드에서 호출해야합니다.
다른 대답에서 알 수 있듯이 GenerateCodeAsync().Result
또는로 가능 GenerateCodeAsync().Wait()
합니다. GenerateCodeAsync
완료 될 때까지 현재 스레드를 차단합니다 .
그러나 귀하의 질문에 태그가 지정되었습니다 asp.net, 그리고 당신은 또한 의견을 남겼습니다 :
asp.net이 많은 코드 줄을 작성하는 것보다 훨씬 쉽게 처리 할 수 있다고 생각하면서 더 간단한 솔루션을 원했습니다.
요점은 ASP.NET의 비동기 메서드를 차단해서는 안된다는 것 입니다. 이렇게하면 웹 앱의 확장 성이 줄어들고 교착 상태가 발생할 수 있습니다 ( await
내부 에 연속 GenerateCodeAsync
이 게시 될 때 AspNetSynchronizationContext
). 사용 Task.Run(...).Result
이 특정 HTTP 요청을 처리하기 위해 하나 이상의 스레드를 초래으로 풀 스레드 다음 블록에 오프로드 뭔가하면, 더 많은 확장 성에게조차 상처를합니다.
ASP.NET을 통해 직접 비동기 컨트롤러를 통해 (웹 API ASP.NET MVC와) 중 하나, 비동기 메서드에 대한 지원 내장 또는했다 AsyncManager
및 PageAsyncTask
고전 ASP.NET에서. 사용해야합니다. 자세한 내용은 이 답변을 확인 하십시오 .
답변
Microsoft Identity에는 비동기 메서드를 동 기적으로 호출하는 확장 메서드가 있습니다. 예를 들어 GenerateUserIdentityAsync () 메서드와 동일한 CreateIdentity ()가 있습니다
UserManagerExtensions.CreateIdentity ()를 보면 다음과 같습니다.
public static ClaimsIdentity CreateIdentity<TUser, TKey>(this UserManager<TUser, TKey> manager, TUser user,
string authenticationType)
where TKey : IEquatable<TKey>
where TUser : class, IUser<TKey>
{
if (manager == null)
{
throw new ArgumentNullException("manager");
}
return AsyncHelper.RunSync(() => manager.CreateIdentityAsync(user, authenticationType));
}
이제 AsyncHelper.RunSync의 기능을 살펴 보겠습니다.
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
{
var cultureUi = CultureInfo.CurrentUICulture;
var culture = CultureInfo.CurrentCulture;
return _myTaskFactory.StartNew(() =>
{
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = cultureUi;
return func();
}).Unwrap().GetAwaiter().GetResult();
}
따라서 이것은 비동기 메소드의 래퍼입니다. 그리고 결과에서 데이터를 읽지 마십시오. ASP에서 코드를 잠재적으로 차단합니다.
나에게는 의심스러운 또 다른 방법이 있지만, 당신도 그것을 고려할 수 있습니다
Result r = null;
YourAsyncMethod()
.ContinueWith(t =>
{
r = t.Result;
})
.Wait();
답변
교착 상태를 방지하기 위해 Task.Run()
@Heinzi가 언급 한 비동기 메소드를 동 기적으로 호출해야 할 때 항상 사용하려고 합니다.
그러나 비동기 메소드가 매개 변수를 사용하는 경우 메소드를 수정해야합니다. 예를 들어 Task.Run(GenerateCodeAsync("test")).Result
오류가 발생합니다.
인수 1 : ‘
System.Threading.Tasks.Task<string>
‘에서 ‘System.Action’으로 변환 할 수 없습니다
대신 다음과 같이 호출 할 수 있습니다.
string code = Task.Run(() => GenerateCodeAsync("test")).Result;
답변
이 스레드에 대한 대부분의 답변은 복잡하거나 교착 상태가 발생합니다.
다음 방법은 간단하며 작업이 끝날 때까지 기다렸다가 결과를 얻기 때문에 교착 상태를 피할 수 있습니다.
var task = Task.Run(() => GenerateCodeAsync());
task.Wait();
string code = task.Result;
또한 여기에 정확히 동일한 내용에 대해 이야기하는 MSDN 기사에 대한 참조가
있습니다. 기본 문맥 /