C # vastync 함수 호출 동기 기능 또는 동기 기능 호출 async 함수
-
12-12-2019 - |
문제
공통 SQL 데이터베이스 작업 (백업, 복원, 실행 스크립트 등)을 수행하기 위해 C # .NET 4.5 라이브러리를 작성했습니다. 이 라이브러리가 콘솔과 GUI 응용 프로그램에서 사용하기 때문에 각 작업에 대해 동기식 및 비동기 기능을 모두 갖고 싶지 만 모든 곳에서 코드를 복제하고 싶지는 않습니다. 그래서 내가 볼 때, 나는 두 가지 옵션이있다 :
-
동기 기능에서 작업을 수행하는 코드를 작성한 다음 즉시 비동기 함수에 대한 작업으로 랩합니다.
public void BackupDB(string server, string db) { // Do all of the work and long running operation here } public async Task BackupDBAsync(string server, string db) { await Task.Factory.StartNew(() => BackupDB(server, db)).ConfigureAwait(false); }
-
비동기 기능에서 작업을 수행하는 코드를 작성하고 .wait () : 를 사용하여 동기 기능에서 호출합니다.
public async Task BackupDBAsync(string server, string db) { // Do all of the work and long running operation here, asynchronously. } public void BackupDB(string server, string db) { BackupDBAsync(server, db).Wait(); // Execution will wait here until async function finishes completely. }
는 다른 옵션보다 낫습니다. 하나는 가장 좋은 방법입니까? 또는 다른 (더 나은) 대안이 있습니까?
나는 그 하나의 경고를 사용하는 것이 async 함수의 모든 기다리시는 명령문이 교착 상태를 피하기 위해 .configureAwait (false)를 사용해야한다는 것입니다 ( in-c"에서 UI에 액세스 할 필요가없는 도서관을 쓰는 이래로 또는 WebContext 나는 그것을 할 수 있도록 안전합니다.
- 편집 : 나는 또한이 질문을 여기서 MSDN 포럼에서 공식 MS 응답을 시도하고 얻을
해결책
이 라이브러리는 콘솔 및 GUI 응용 프로그램 모두 에서이 라이브러리가 사용되므로 각 작업에 대해 동기식 및 비동기 기능을 모두 갖고 싶지 만 모든 곳에서 코드를 복제하고 싶지는 않습니다.
가장 좋은 대답은 다음과 같습니다.하지 마십시오.
스티븐 Toub에는이 주제에 대한 두 가지 우수한 블로그 게시물이 있습니다 :
다른 팁
일부 응용 프로그램이 동기식으로로드 될 데이터와 다른 ASYC가 필요한 것과 비슷한 상황이있었습니다.나는 Dataloader를 호출 한 인터페이스를 만들기로 결정했습니다.
public interface IIMViewModelDL {
void LoadProjects(AssignProjects callback);
}
.
AssignProjects 콜백은 반환 된 프로젝트 목록을 수행하는 간단한 대리자입니다.
public delegate void AssignProjects(IEnumerable<Project> results);
.
이제이 아름다움은 동기화 또는 비동기에서 렌일링 여부를 알지 못하지 않고 인터페이스로 작업 할 수 있습니다.
세 개의 클래스가 생성됩니다. 하나의 기본, 하나의 동기화 및 하나의 비동기 :
public abstract class BaseViewModelDL {
protected IEnumerable<Project> LoadProjects() {
BaseServiceClient client = new BaseServiceClient();
return client.Projects();
}
public class SynchronousViewModelDL : BaseViewModelDL, IIMViewModelDL {
public void LoadProjects(AssignProjects callback) {
callback(base.LoadProjects());
}
public class AsyncIMViewModelDL : BaseViewModelDL, IIMViewModelDL {
public void LoadProjects(AssignProjects callback) {
BackgroundWorker loadProjectsAsync = new BackgroundWorker();
loadProjectsAsync.DoWork += new DoWorkEventHandler(LoadProjectsAsync_DoWork);
loadProjectsAsync.RunWorkerCompleted += new RunWorkerCompletedEventHandler(LoadProjectsAsync_RunWorkerCompleted);
loadProjectsAsync.RunWorkerAsync(callback);
}
void LoadProjectsAsync_DoWork(object sender, DoWorkEventArgs e) {
var results = new ObservableCollection<Project>(base.LoadProjects());
e.Result = new object[] { results, e.Argument };
}
void LoadProjectsAsync_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
AssignProjects callback = (AssignProjects)((object[])e.Result)[1];
IEnumerable<Project> results = (IEnumerable<Project>)((object[])e.Result)[0];
callback(results);
}
.
이제 응용 프로그램에서 데이터를로드하려는 방법을 결정할 수 있습니다 ... 이것은 IOC 컨테이너를 통해 주입 될 수 있지만 데모 목적으로 하드 코딩 된 것입니다.
private ViewModelDataLoaders.IIMViewModelDL dataLoader = new ViewModelDataLoaders.AsyncIMViewModelDL();
.
이제 호출 코드가 동일하게 보입니다. vastync 또는 sync인지 여부에 대한 현명한 사람은 없습니다.
private void LoadProjects() {
dataLoader.LoadProjects(
delegate(IEnumerable<Project> results) {
Projects = new ObservableCollection<Project>(results);
});
}
.
단위 테스트 (동기화), WPF 응용 프로그램 (ASYNC) 및 콘솔 응용 프로그램 (동기화)에 대해 정기적으로 사용합니다.
기다리고 사용하지 않고 비동기로 메소드를 만드는 방법이되는 것은 아닙니다. 비동기를 비동기화하지 않으므로 기다리고 있으면 기다리십시오 (AWAIT에서 실행 된 코드는 비동기식이 일어나는 일이 발생한 다음 나머지 비동기 메소드가 비동기 적으로 수행됩니다). / P>
전형적으로, async 키워드에 의해 수정 된 방법은 적어도 하나의 기다린 표현식 또는 명령문을 포함한다. 이 방법은 첫 번째 기다리는 표현식에 도달 할 때까지 동기식으로 실행됩니다.이 가리키는 작업이 완료 될 때까지 일시 중단됩니다. 그 동안 제어자가 메소드의 발신자에게 반환됩니다. 메서드에 AWAIT Expression 또는 Statement가 포함되어 있지 않으면 동 기적으로 실행됩니다. 컴파일러 경고는 해당 상황이 오류를 나타낼 수 있으므로 기다리지 않는 ASYNC 메소드로 알려줍니다. 자세한 내용은 컴파일러 경고 CS4014를 참조하십시오.
: Async / P>