Для этого вам нужно использовать Stripe Connect .
В принципе, платформа (= вы) будет иметь свою собственную учетную запись Stripe, и каждая пожертвовательная кампания будет иметь свою собственную учетную запись , связанный с вашими (это означает, что они предоставили вам разрешения принимать платежи от их имени).
Затем вы могли бы создать для них плату , используя application_fee
, чтобы указать ваш раскол. Существует два разных способа, которые описаны здесь: https://stripe.com/docs/connect/payments-fees .
int[] ids = new[] { 1, 2, 3, 4, 5 };
Parallel.ForEach(ids, i => DoSomething(1, i, blogClient).Wait());
Несмотря на то, что вы выполняете операции параллельно с указанным выше кодом, этот код блокирует каждый поток, в котором выполняется каждая операция. Например, если сетевой вызов занимает 2 секунды, каждый поток висит в течение 2 секунд без каких-либо действий, кроме ожидания.
int[] ids = new[] { 1, 2, 3, 4, 5 };
Task.WaitAll(ids.Select(i => DoSomething(1, i, blogClient)).ToArray());
С другой стороны, приведенный выше код с WaitAll
также блокирует нити и ваши потоки не будут свободны обрабатывать любую другую работу до окончания операции.
Я предпочел бы WhenAll
, который будет выполнять ваши операции асинхронно в Parallel.
public async Task DoWork() {
int[] ids = new[] { 1, 2, 3, 4, 5 };
await Task.WhenAll(ids.Select(i => DoSomething(1, i, blogClient)));
}
Фактически, в приведенном выше case, вам даже не нужно
await
, вы можете просто прямо вернуться из метода, поскольку у вас нет никаких продолжений:blockquote>public Task DoWork() { int[] ids = new[] { 1, 2, 3, 4, 5 }; return Task.WhenAll(ids.Select(i => DoSomething(1, i, blogClient))); }
Чтобы поддержать это, здесь представляет собой подробное сообщение в блоге, в котором рассматриваются все альтернативы и их преимущества / недостатки: Как и где параллельный асинхронный ввод-вывод с веб-интерфейсом ASP.NET
Мне было любопытно увидеть результаты методов, предоставленных в вопросе, а также принятый ответ, поэтому я поставил его на тест.
Вот код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace AsyncTest
{
class Program
{
class Worker
{
public int Id;
public int SleepTimeout;
public async Task DoWork(DateTime testStart)
{
var workerStart = DateTime.Now;
Console.WriteLine("Worker {0} started on thread {1}, beginning {2} seconds after test start.",
Id, Thread.CurrentThread.ManagedThreadId, (workerStart-testStart).TotalSeconds.ToString("F2"));
await Task.Run(() => Thread.Sleep(SleepTimeout));
var workerEnd = DateTime.Now;
Console.WriteLine("Worker {0} stopped; the worker took {1} seconds, and it finished {2} seconds after the test start.",
Id, (workerEnd-workerStart).TotalSeconds.ToString("F2"), (workerEnd-testStart).TotalSeconds.ToString("F2"));
}
}
static void Main(string[] args)
{
var workers = new List<Worker>
{
new Worker { Id = 1, SleepTimeout = 1000 },
new Worker { Id = 2, SleepTimeout = 2000 },
new Worker { Id = 3, SleepTimeout = 3000 },
new Worker { Id = 4, SleepTimeout = 4000 },
new Worker { Id = 5, SleepTimeout = 5000 },
};
var startTime = DateTime.Now;
Console.WriteLine("Starting test: Parallel.ForEach...");
PerformTest_ParallelForEach(workers, startTime);
var endTime = DateTime.Now;
Console.WriteLine("Test finished after {0} seconds.\n",
(endTime - startTime).TotalSeconds.ToString("F2"));
startTime = DateTime.Now;
Console.WriteLine("Starting test: Task.WaitAll...");
PerformTest_TaskWaitAll(workers, startTime);
endTime = DateTime.Now;
Console.WriteLine("Test finished after {0} seconds.\n",
(endTime - startTime).TotalSeconds.ToString("F2"));
startTime = DateTime.Now;
Console.WriteLine("Starting test: Task.WhenAll...");
var task = PerformTest_TaskWhenAll(workers, startTime);
task.Wait();
endTime = DateTime.Now;
Console.WriteLine("Test finished after {0} seconds.\n",
(endTime - startTime).TotalSeconds.ToString("F2"));
Console.ReadKey();
}
static void PerformTest_ParallelForEach(List<Worker> workers, DateTime testStart)
{
Parallel.ForEach(workers, worker => worker.DoWork(testStart).Wait());
}
static void PerformTest_TaskWaitAll(List<Worker> workers, DateTime testStart)
{
Task.WaitAll(workers.Select(worker => worker.DoWork(testStart)).ToArray());
}
static Task PerformTest_TaskWhenAll(List<Worker> workers, DateTime testStart)
{
return Task.WhenAll(workers.Select(worker => worker.DoWork(testStart)));
}
}
}
И полученный результат:
Starting test: Parallel.ForEach...
Worker 1 started on thread 1, beginning 0.21 seconds after test start.
Worker 4 started on thread 5, beginning 0.21 seconds after test start.
Worker 2 started on thread 3, beginning 0.21 seconds after test start.
Worker 5 started on thread 6, beginning 0.21 seconds after test start.
Worker 3 started on thread 4, beginning 0.21 seconds after test start.
Worker 1 stopped; the worker took 1.90 seconds, and it finished 2.11 seconds after the test start.
Worker 2 stopped; the worker took 3.89 seconds, and it finished 4.10 seconds after the test start.
Worker 3 stopped; the worker took 5.89 seconds, and it finished 6.10 seconds after the test start.
Worker 4 stopped; the worker took 5.90 seconds, and it finished 6.11 seconds after the test start.
Worker 5 stopped; the worker took 8.89 seconds, and it finished 9.10 seconds after the test start.
Test finished after 9.10 seconds.
Starting test: Task.WaitAll...
Worker 1 started on thread 1, beginning 0.01 seconds after test start.
Worker 2 started on thread 1, beginning 0.01 seconds after test start.
Worker 3 started on thread 1, beginning 0.01 seconds after test start.
Worker 4 started on thread 1, beginning 0.01 seconds after test start.
Worker 5 started on thread 1, beginning 0.01 seconds after test start.
Worker 1 stopped; the worker took 1.00 seconds, and it finished 1.01 seconds after the test start.
Worker 2 stopped; the worker took 2.00 seconds, and it finished 2.01 seconds after the test start.
Worker 3 stopped; the worker took 3.00 seconds, and it finished 3.01 seconds after the test start.
Worker 4 stopped; the worker took 4.00 seconds, and it finished 4.01 seconds after the test start.
Worker 5 stopped; the worker took 5.00 seconds, and it finished 5.01 seconds after the test start.
Test finished after 5.01 seconds.
Starting test: Task.WhenAll...
Worker 1 started on thread 1, beginning 0.00 seconds after test start.
Worker 2 started on thread 1, beginning 0.00 seconds after test start.
Worker 3 started on thread 1, beginning 0.00 seconds after test start.
Worker 4 started on thread 1, beginning 0.00 seconds after test start.
Worker 5 started on thread 1, beginning 0.00 seconds after test start.
Worker 1 stopped; the worker took 1.00 seconds, and it finished 1.00 seconds after the test start.
Worker 2 stopped; the worker took 2.00 seconds, and it finished 2.00 seconds after the test start.
Worker 3 stopped; the worker took 3.00 seconds, and it finished 3.00 seconds after the test start.
Worker 4 stopped; the worker took 4.00 seconds, and it finished 4.00 seconds after the test start.
Worker 5 stopped; the worker took 5.00 seconds, and it finished 5.00 seconds after the test start.
Test finished after 5.00 seconds.
Поскольку API, который вы вызываете, является асинхронным, версия Parallel.ForEach
не имеет большого смысла. Вы не должны использовать .Wait
в версии WaitAll
, так как это потеряло бы параллелизм. Другая альтернатива, если вызывающий абонент async использует Task.WhenAll
после выполнения Select
и ToArray
для генерации массива задач. Второй альтернативой является использование Rx 2.0
Вы можете использовать функцию Task.WhenAll
, которую вы можете передать n ; Task.WhenAll
вернет задачу, которая завершится, когда все задачи, которые вы передали в Task.WhenAll
, завершатся. Вы должны ждать асинхронно на Task.WhenAll
, чтобы не блокировать поток пользовательского интерфейса:
public async Task DoSomeThing() {
var Task[] tasks = new Task[numTasks];
for(int i = 0; i < numTask; i++)
{
tasks[i] = CallSomeAsync();
}
await Task.WhenAll(tasks);
// code that'll execute on UI thread
}