Я пытаюсь создать библиотеку протоколирования, и все будет хорошо, пока не вызывается выключение приложения. Когда вызывается выключение приложения, любой незавершенный поток убивается, а конкретный журнал теряется.C# .Net - Как сделать приложение до тех пор, пока все потоки, созданные в Библиотеке, не будут завершены.
В настоящее время приложение выходит даже до завершения первых 10 потоков. Мне нужна помощь в том, как заставить приложение ждать, пока все потоки, созданные библиотекой, не будут выполнены.
ПРИМЕЧАНИЕ: Требование, которое я получил, такое. Изменения должны быть только в классе «Регистрация», поскольку это будет библиотека и будет предоставлена конечным пользователям. В этом случае необходимо выполнить обработку проблем с журналом при отключении приложения. Здесь у меня проблемы.
В качестве альтернативы решение, например, создать событие в классе ведения журнала, чтобы вызвать полное завершение ведения журнала, и попросить пользователя вызвать выход приложения на это событие, возможно, но этого я стараюсь избегать, поскольку он добавляет эту нагрузку для конечного пользователя и добавляет сложность реализации. Есть вероятность, что они могут пропустить это, чего я не хочу. Я ищу решение, как пользователь должен сделать «Logging.AddException (....)», а затем забудьте об этом.
Пожалуйста, помогите. Предоставьте комментарии, если вы не совсем поняли эту идею.
Вот полный текст, который вы можете добавить в консольное приложение. Примечания: Посмотрите на комментарии в случае 1 и СЛУЧАЕ 2.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MultithreadKeepAlive
{
class Program
{
static void Main(string[] args)
{
LogLoadTest();
Logging.AddExceptionEntryAsync(new Exception("Last Exception"));
/*
* USE CASE 1: Enable the below lines and you will see how long it is supposed to take.
* Notice that currentDomain_ProcessExit will not trigger if below gets uncommented
*/
//Console.WriteLine("Main thread wait override");
//Console.ReadLine();
}
static void LogLoadTest()
{
//In real world this will be called from any place of application like startup or just after application shutdown is initiated.
//: NOTICE: Unlike the sample here, this will never be on loop and I am not looking for handling multithreads in this class.
// That responsibility I am planning to assign to Logging class.
// AND ALSO the class Logging is going to be in a seperate signed assembly where user of this class ('Program') should not worry about multithreads.
Task t;
for (int i = 0; i < 40; i++)
{
t = Logging.AddExceptionEntryAsync(new Exception("Hello Exception " + i), "Header info" + i);
}
}
}
public class Logging
{
static List<Task> tasks = new List<Task>();
static AppDomain currentDomain;
static Logging()
{
currentDomain = AppDomain.CurrentDomain;
currentDomain.ProcessExit += currentDomain_ProcessExit;
}
public static async Task AddExceptionEntryAsync(Exception ex, string header = "")
{
Task t = Task.Factory.StartNew(() => AddExceptionEntry(ex, header));
tasks.Add(t);
await t;
}
public static void AddExceptionEntry(Exception ex, string header)
{
/* Exception processing and write to file or DB. This might endup in file locks or
* network or any other cases where it will take delays from 1 sec to 5 minutes. */
Thread.Sleep(new Random().Next(1, 1000));
Console.WriteLine(ex.Message);
}
static void currentDomain_ProcessExit(object sender, EventArgs e)
{
Console.WriteLine("Application shutdown triggerd just now.");
Process.GetCurrentProcess().WaitForExit(); //1st attempt.
//Task.WaitAll(tasks.ToArray()); //2nd attempt
while (tasks.Any(t => !t.IsCompleted)) //3rd attempt.
{
}
/* USE CASE 2: IF WORKING GOOD, THIS WILL BE DISPLAYED IN CONSOLE AS LAST
* MESSAGE OF APPLICATION AND WILL WAIT FOR USER. THIS IS NOT WORKING NOW.*/
Console.WriteLine("All complete"); //this message should show up if this work properly
Console.ReadLine(); //for testing purpose wait for input from user after every thread is complete. Check all 40 threads are in console.
}
}
}
Пробовал это с помощью функции нити join()? Если вы выходите, вы можете вызвать метод для каждого работающего потока. Таким образом, программа ждет, пока они не закончатся. –
Почему эта функция: 'AddExceptionEntryAsync (Exception ex, string header)' не помечена 'async' и просто использует' Task.Delay' внутри нее? Прочитали ли вы документацию по ['Process.Exit'] (https://msdn.microsoft.com/en-us/library/system.appdomain.processexit (v = vs.110) .aspx)? В частности, эта часть * «Общее время выполнения всех обработчиков событий ProcessExit ограничено, так же как ** полное время выполнения всех финализаторов ограничено при завершении процесса.Значение по умолчанию - две секунды **. Неуправляемый хост может изменить это время выполнения, вызвав метод со значением перечисления. »* –
Рон Бейер, lorenz albert: все они пробовали. Они работают в нормальных сценариях, где приложение работает как обычно. Здесь, когда закрытие приложения ничего не мешает ему убить все темы, которые я пробовал, уничтожаются, а приложение существует без записи журналов. –