我有以下代码:
myObject object1 = null;
Thread obj1Thread = new Thread(() => { object1 = _myService.GetMethod(variable1, variable2); });
obj1Thread.Start();
obj1Thread.Join();
myObject object2 = null;
Thread obj2Thread = new Thread(() => { object2 = _myService.GetMethod2(variable3, variable4); });
obj2Thread.Start();
obj2Thread.Join();
据我了解,这段代码将创建2个新线程,运行指定的方法,暂停主线程,直到两个线程都完成,然后继续执行。
假设我说的是正确的,到目前为止一切都很好。
接下来,我想尝试一下:
myObject object1 = null;
Thread obj1Thread = new Thread(async () => { object1 = await _myService.GetMethod(variable1, variable2); });
obj1Thread.Start();
obj1Thread.Join();
myObject object2 = null;
Thread obj2Thread = new Thread(async () => { object2 = await _myService.GetMethod2(variable3, variable4); });
obj2Thread.Start();
obj2Thread.Join();
基本上向每个线程添加异步并等待。
编译器接受此更改,并且似乎在本地运行,但是此代码还可以,并且是否有可能导致我进一步遇到任何问题,例如,线程会变得混乱,无法等待,混淆结果等
我对异步有相当好的理解,对多线程也有基本的了解,而且我无法想到为什么它不起作用。
代码在本地运行,但是我担心的是,在服务器上负载很重的情况下,可能会出现本地版本中不存在的问题。...
答案 0 :(得分:2)
您的代码可以并行并且异步等待,只需一行:
await Task.WhenAll(_myService.GetMethod(variable1, variable2), _myService.GetMethod2(variable3, variable4)).
这就是您所需要的。没有线程。没有加入。如果这些方法确实是I / O,则将没有线程。
与往常一样,必须阅读:https://blog.stephencleary.com/2013/11/there-is-no-thread.html
如果您的方法返回不同的结果并且需要分配给变量,则可以执行以下操作:
Task<int> task1 = _myService.GetMethod(variable1, variable2);
Task<string> task2 = _myService.GetMethod2(variable3, variable4);
// Both tasks started.
int a = await task1; // Wait for first task
string b = await task2; // If this already finished, it will just return the result
答案 1 :(得分:2)
编译器接受此更改,并且似乎在本地运行,但是此代码还可以,并且是否有可能导致我进一步遇到任何问题,例如,线程会变得混乱,无法等待,混淆结果等
我对异步有相当好的理解,对多线程也有基本的了解,而且我无法想到为什么它不起作用。
是的,这个代码将导致您的问题。像您期望的线程不等待。您正在将async void
lambda传递给Thread
构造函数,并且该线程在到达该lambda中的await
之前,将退出, 它设置object1
/ object2
变量。因此,这些变量完全有可能在null
之后保留Join
。
在适当的解决方案,因为FCin posted,是使用异步并发性。 (I避免术语“平行”在这里,以减少与Parallel
类型和任务并行库混乱)。异步并发使用Task.WhenAll
:
// Start both methods concurrently
var task1 = _myService.GetMethod(variable1, variable2);
var task2 = _myService.GetMethod2(variable3, variable4);
// (Asynchronously) wait for them both to complete.
await Task.WhenAll(task1, task2);
// Retrieve results.
myObject object1 = await task1;
myObject object2 = await task2;
答案 2 :(得分:0)
您上面的代码没有利用线程,它阻塞了第一个线程,直到完成,然后启动了第二个
obj1Thread.Join();
指示您的主线程等待obj1Thread退出后再继续。这意味着它将旋转obj1Thread然后等待它完成,这意味着:
您想这样做:
myObject object1 = null;
Thread obj1Thread = new Thread(async () => { object1 = await _myService.GetMethod(variable1, variable2); });
obj1Thread.Start();
myObject object2 = null;
Thread obj2Thread = new Thread(async () => { object2 = await _myService.GetMethod2(variable3, variable4); });
obj2Thread.Start();
obj1Thread.Join();
obj2Thread.Join();