чтобы рабочий поток мог работать с этой локальной очередью без использования блокировк
Когда рабочий поток видит что делать ему больше нечего, то есть его локальная очередь пустая, он пытается своровать задачу у другого рабочего потока. Но ворует он элементы с хвоста чужой локальной очереди.
// эта функция выполняется в потоке #1
void DoSmth()
{
Task.Run(
// этот делегат выполняется тоже в потоке #1 и только после того, как поток полностью завершит тяжелые вычисления в DoHeavyCalculations
x => CallNetworkService()
);
DoHeavyCalculations();
}
// эта функция выполняется в потоке #1
void DoSmth()
{
DoHeavyCalculations();
CallNetworkService();
}
void DoSmth()
{
Task<int> networkTask = Task.Run(
// этот делегат выполняется тоже в потоке #1 и только после того, как поток полностью завершит тяжелые вычисления в DoHeavyCalculations и в DoSmthWithInteger, но DoSmthWithInteger никогда не завершится, т.к. зависит от вызова GetIntegerFromNetworkService (получается взаимная блокировка).
x => {return GetIntegerFromNetworkService();}
);
DoHeavyCalculations();
// невозможно вызвать DoSmthWithInteger, потому что мы никогда не получим значение networkTask.Result
DoSmthWithInteger(networkTask.Result);
}
По-моему, 1-й вариант будет быстрее, так как не будет тратиться время на переключение контекста. Так что преимущества может не быть, если говорить о некой абстрактной вычислительной задаче.
У сервера есть 1000 клиентов и на каждого из них при его запросе будет открыватся асинхронная операция — либо паралельные вычисления либо I/O. И мы очень легко получим это «исчерпение». Но для такого сервера нужно лимитировать число одновременных клиентов для которых запускаются асинхронные операции. Т.е. для 1000 клиентов к примеру открываем, остальные будут ждать.
Если они будут в одном, то даже если поток имеет данные он не может начать работу пока другой не закончит свою
Попробуйте написать 2 бесконечных цикла и запустить их в 2 потока на одном ядре)
Но лучше сделать это на сервере, а не средствами СУБД имхо, два запроса при добавлении суммы.
CROSS APPLY has its obvious usage in allowing a set to depend on another (unlike the JOIN operator)
it behaves like a function that operates over each member of the left set, so, in SQL Server terms it always perform a Loop Join, which almost never is the best way to join sets.
А еще может применить параметризованную функцию к каждой строке и присоединить ее результат.
SELECT SomeFunction(BB.B1),
BB.B2,
A.A1
FROM [dbo].[A] as A
cross join (select top 1 B.B1, B.B2 from [dbo].[B] as B where A.BId = B.Id) as BB
using (var transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions {IsolationLevel = IsolationLevel.Snapshot}))
{
using (var dbContext = new DB())
{
var data1= new Data1();
dbContext.Table1.Add(data1);
dbContext.SaveChanges();
}
transactionScope.Complete();
//#1
}
//#2
#1
var host = new ServiceHost(typeof(AuthenticationService), serviceUri);
#2
host.Open();
#3
Именно многопоточность позволяла запускать несколько приложений одновременно на одноядерном процессоре.
Даю подсказку: пользователю назначается группа по-умолчанию.
Там есть множественные связи пользователя с группами и ролями. Итоговые роли являются суммой ролей групп и индивидуальных ролей
Логично же было делать так: раз кортеж (анонимный объект в круглых скобках) маппится на ValueTuple , то кортеж-класс (анонимный объект в фигурных скобках) должен маппиться на Tuple.
Ну, или если оставлять анинимные классы, как сейчас они есть, то нужно отдельный синтаксис для классов-кортежей, типа такого