C # Connectez-vous à la database dans un fil séparé

J'ai une application qui se trouve dans la barre des tâches et vérifie périodiquement une database (via SQLConnection). Si la database est inaccessible, elle affiche simplement un statut rouge sur l'icône de notification, et rien d'autre. Ceci est prévu puisque les users seront sur des ordinateurs portables voyageant entre les installations, et la database n'est accessible que sur un réseau interne ou lorsqu'il est connecté via VPN.

Le problème que j'ai est que lorsque la database est inaccessible, je voudrais toujours que le menu contextuel de l'icône de notification soit réactif. Actuellement, si l'user tente d'interagir avec le menu pendant que la database tente de se connecter, le thread est verrouillé avec la tentative de connection.

Ce que j'aimerais, c'est que la connection à la database se fasse dans un thread séparé, mais je sais que le partage de l'object de connection entre les threads est une mauvaise chose à faire. Une fois la database connectée, je dois l'interroger depuis le thread d'origine. Y a-t-il un bon moyen de le faire?

Je sais que je pourrais avoir une fonction qui rus dans un nouveau thread et vérifie simplement si la connection échoue ou non, alors si cela returnne le succès, le thread d'origine pourrait se déplacer et connecter son propre object de database. Mais cette méthode semble être une mauvaise solution. Des idées?

Merci!


Merci pour les suggestions – j'ai beaucoup appris d'eux. En fin de count, j'ai fait ce que j'aurais dû faire depuis le début. Le thread principal (UI) lance juste un nouveau thread (qui inclut la création d'object de database et la connection) chaque fois qu'une mise à jour périodique de database est nécessaire.

Ainsi, comme HenkHolterman l'a suggéré dans un commentaire à mon message original, je n'avais vraiment pas besoin de créer la database et d'exécuter des opérations avec lui dans des threads séparés.

Je serai certainement intéressé à utiliser SqlConnection.OpenAsync une fois que j'ai fait la mise à niveau vers VS2010.

Merci encore.

Une SqlConnection n'a pas d'exigences d'affinité de threads, vous pouvez donc créer et l'ouvrir sur un thread séparé et transmettre la reference au thread de l'interface user. Tant que vous n'appelez pas de propriétés ou de methods sur la même instance simultanément à partir de plusieurs threads, vous ne devriez avoir aucun problème.

Utilisez la class Task (System.Threading.Task) pour démarrer cette opération en arrière-plan, puis appelez ContinueWith pour transférer la propriété de l'instance vers le thread d'interface user.

 public class TrayIconForm : Form { private SqlConnection connection = null; private void Form_Load(object sender, EventArgs args) { TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext(); Task.Factory.StartNew(() => { var sql = new SqlConnection(); sql.ConnectionSsortingng = "your connection ssortingng"; sql.Open(); return sql; }).ContinueWith((task => { connection = task.Result; // You can access other UI elements here as needed. }), ui); } } 

Avec les nouveaux mots-keys async et await à introduire dans C # 5.0 et disponibles maintenant via le CTP Async, vous pouvez le faire.

 private async void Form_Load(object sender, EventArgs args) { connection = await Task.Run(() => // TaskEx.Run in the CTP { var sql = new SqlConnection(); sql.ConnectionSsortingng = "your connection ssortingng"; sql.Open(); return sql; }); } 

Je recommand d'utiliser le nouveau CTP Async C #. Cela vous permettra de restr sur le fil de l'interface user, réduisant ainsi la complexité.

SqlConnection.OpenAsync

L'utilisation d'un object BackgroundWorker devrait résoudre votre problème de manière simple, bien que plus précisément vous souhaitiez utiliser le thread pour essayer d'ouvrir la connection, laissant le thread de l'interface user prêt à recevoir les inputs de l'user.