loop.run_forever()
действительно будет работать вечно, даже если внутри нет задач. Хорошей новостью является то, что вам не нужна эта функция. Чтобы дождаться завершения ваших вычислений, используйте asyncio.gather
:
class FibonacciCalculatorAsync:
def __init__(self):
self.pool = ThreadPoolExecutor(max_workers=2)
# self.loop = asyncio.get_event_loop()
...
async def calculate(self, n):
loop = asyncio.get_running_loop()
result = await loop.run_in_executor(self.pool, self.calculate_sync, n)
print(result)
async def main():
calculator = FibonacciCalculatorAsync()
fib_35 = asyncio.ensure_future(calculator.run(35))
fib_32 = asyncio.ensure_future(calculator.run(32))
print("initial thread can continue its work")
...
# demand fibonaccy computation has ended
await asyncio.gather(fib_35, fib_32)
if __name__ == '__main__':
asyncio.run(main())
Обратите внимание, как обрабатывается цикл - я изменил несколько вещей. Если вы начнете использовать asyncio, я бы порекомендовал иметь один цикл для всех вещей вместо того, чтобы создавать циклы для более детальной задачи. При таком подходе вы получаете все асинхронные навороты для обработки и синхронизации задач.
Кроме того, из-за GIL невозможно распараллелить чистый код без ввода-вывода Python в ThreadPoolExecutor
. Помните об этом и в таких случаях предпочитайте исполнителя пула процессов.
Это могло бы быть наивно, но как насчет:
static string[] MultiStringToArray(string multiString)
{
return multiString.TrimEnd('\0').Split('\0');
}
Также - не Вы пропускающий финал И могло бы быть легче звонить, если бы массив был a \0
(Вы заявляете double-null-terminated) в StringArrayToMultiString
?params string[]
массив - что-то как:
static string StringArrayToMultiString(params string[] values)
{
if (values == null) throw new ArgumentNullException("values");
StringBuilder multiString = new StringBuilder();
foreach (string s in values)
{
multiString.Append(s);
multiString.Append('\0');
}
return multiString.ToString();
}
[отредактированный после разъяснения о заключительных \0]
Я протестировал метод StringArrayToMultiString, с помощью ChangeServiceConfig () функция для изменения зависимостей службы Windows, и это работает приятно на нуль, один и много строк.
Тем временем я разработал решение для декодирования мультистроки, полученной от вызова API. Например, SCardListReaders () функция возвращает мультистроку имен читателя ПК/SC. Я объявил это как:
[DllImport("winscard.dll", CharSet = CharSet.Auto)]
static extern int SCardListReaders(
IntPtr context,
string groups,
char[] readers,
ref uint readersLen
);
Обратите внимание, что параметр читателей, который возвращает мультистроку, объявляется как символ []. Возвращаемое значение легко анализируется и преобразовывается в набор строк:
static string[] MultiStringToArray(
char[] multistring
)
{
List<string> stringList = new List<string>();
int i = 0;
while (i < multistring.Length)
{
int j = i;
if (multistring[j++] == '\0') break;
while (j < multistring.Length)
{
if (multistring[j++] == '\0')
{
stringList.Add(new string(multistring, i, j - i - 1));
i = j;
break;
}
}
}
return stringList.ToArray();
}
В документации MSDN для RegistryKey.SetValue () и RegistryKey.GetValue () примеры просто передаются или преобразуются в строку [] соответственно. Что-то не так?