Question

Je suis nouveau fils et dans le besoin d'aide. J'ai une application de saisie de données qui prend une quantité exorbitante de temps pour insérer un nouvel enregistrement (i.e. 50-75 secondes). Donc, ma solution était d'envoyer une instruction d'insertion via un ThreadPool et permettre à l'utilisateur de commencer à saisir les données de l'enregistrement alors que insert qui retourne un nouvel ID d'enregistrement alors que cet insert est en cours d'exécution. Mon problème est qu'un utilisateur peut frapper sauver avant le nouvel ID est renvoyé par cet insert.

J'ai essayé de mettre dans une variable booléenne qui se définie sur true par un événement de ce fil quand il est sûr de sauver. Je me suis alors mis dans

while (safeToSave == false)  
{  
    Thread.Sleep(200)  
}  

Je pense que c'est une mauvaise idée. Si je lance la méthode de sauvegarde avant que les rendements de bande de roulement, il est bloqué.

Alors mes questions sont:

  1. Y at-il une meilleure façon de le faire?
  2. Qu'est-ce que je fais mal ici?

Merci pour toute aide.
Doug

Modifier pour plus d'informations:

Il fait un insert dans une très grande (approche taille max) base de données FoxPro. Le fichier a environ 200 champs et presque autant d'index sur elle.
Et avant de vous demander, non, je ne peux pas changer la structure telle qu'elle était ici avant que j'étais et il y a une tonne de code existant frappant. Le premier problème est, afin d'obtenir un nouvel ID je dois d'abord trouver le max (id) dans le tableau puis incrémenter et la somme de contrôle il. Cela prend environ 45 secondes. Ensuite, le premier insert est simplement et insert de ce nouvel identifiant et un champ enterdate. Ce tableau ne / ne peut pas être mis dans un DBC afin que les règles sur ids génératrices automobiles et autres.

@ joshua.ewer Vous avez le proccess correct et je pense que pour le court terme, je vais simplement désactiver le bouton d'enregistrement, mais je regarderez dans votre idée de passer dans une file d'attente. Avez-vous des références à MSMQ que je jeter un oeil à?

Était-ce utile?

La solution

Tout le monde, y compris vous, abordé les problèmes de base (temps d'insertion, pourquoi vous faites un insert, puis mettre à jour), donc je vais coller avec seulement les préoccupations techniques avec votre solution proposée. Donc, si je reçois le droit de débit:

  • Thread 1: saisie de données pour démarrer enregistrement

  • Discussion 2: Contexte appelle à DB pour récupérer les nouveaux Id

  • Le bouton d'enregistrement est toujours activé, si l'utilisateur tente d'enregistrer avant de fil 2 finalise, vous mettez # 1 dormir 200 ms?

Le plus simple, non plus, la réponse est d'avoir juste le bouton désactivé et avoir ce fil faire un rappel à un délégué qui permet le bouton. Ils ne peuvent pas commencer l'opération de mise à jour jusqu'à ce que vous êtes sûr que les choses sont mises en place de façon appropriée.

Bien, je pense une bien meilleure solution (mais il pourrait être exagéré si vous êtes juste la construction d'une extrémité avant Q & D à FoxPro), serait de jeter les opérations de sauvegarde dans une file d'attente. L'utilisateur peut saisir le plus rapidement possible, les demandes sont mis en quelque chose comme MSMQ et ils peuvent compléter dans leur temps de manière asynchrone.

Autres conseils

1) Beaucoup :), vous pouvez par exemple désactiver le bouton « enregistrer », tandis que le fil est d'insérer l'objet, ou vous pouvez configurer un travailleur de fil qui gère une file d'attente de « sauver demandes » (mais je pense que le problème ici est que l'utilisateur souhaite modifier l'enregistrement nouvellement créé, afin de désactiver le bouton peut-être il vaut mieux)

2) Je pense que nous avons besoin d'un peu plus du code pour pouvoir comprendre ... (ou est peut-être un problème de synchronisation, je ne suis pas fan de bug de fils trop)

BTW, je ne comprends pas pourquoi un insert devrait prendre si long..I penser que vous devriez vérifier que le code premier! <- comme Charles déclaré avant (désolé, dind't lire le post):)

Utilisez un futur plutôt que d'une action de ThreadPool brut. Exécutez l'avenir, permettre à l'utilisateur de faire tout ce qu'ils veulent, quand ils ont frappé Enregistrer sur le 2ème disque, demander la valeur de l'avenir. Si le 1er insert déjà fini, vous aurez l'ID tout de suite et le 2ème insert sera autorisé à coup d'envoi. Si vous attendez toujours sur la 1ère opération, l'avenir bloquera jusqu'à ce qu'il soit disponible, puis la 2ème opération peut exécuter.

Vous n'êtes pas économiser tout temps à moins que l'utilisateur est plus lent que l'opération.

D'abord, vous devriez probablement trouver et corriger, la raison pour laquelle un insert prend tellement de temps ... 50-75 secondes est déraisonnable pour une base de données moderne pour une seule insertion de la ligne, et indique que quelque chose d'autre a besoin d'être adressée, comme les indices, ou le blocage ...

En second lieu, pourquoi vous insérez le disque avant d'avoir les données? Normalement, les applications d'entrée de données sont codées de telle sorte que l'insert ne soit pas tenté jusqu'à ce que toutes les données nécessaires à l'insertion ont été recueillies auprès de l'utilisateur. Est-ce que vous faites cela parce que vous essayez d'obtenir le nouvel ID de retour de la base de données d'abord, puis « mettre à jour » le nouvel enregistrement vide avec les données entrées par l'utilisateur plus tard? Si oui, presque tous les fournisseurs de base de données dispose d'un mécanisme où vous pouvez faire l'insert une seule fois, sans connaître le nouvel ID, et ont la base de données retourner la nouvelle ID et ... Qu'est-ce que la base de données fournisseurs utilisez-vous?

est une telle solution possible:

Pre-calculer les ID uniques avant qu'un utilisateur commence à ajouter encore. Gardez une liste des ID uniques qui sont déjà dans le tableau mais placent les porteurs. Lorsqu'un utilisateur tente d'insérer, les réserver un des identifiants uniques, lorsque l'utilisateur presse économisent, ils remplacent maintenant l'endroit porte avec leurs données.

PS: Il est difficile de le confirmer, mais être au courant de la question de la concurrence suivante avec ce que vous proposez (avec ou sans fils): l'utilisateur A, commence à ajouter, l'utilisateur B commence à ajouter, l'utilisateur A calcule ID 1234 l'ID libre max, l'utilisateur B calcule ID 1234 comme ID libre max. L'utilisateur insère des ID 1234, insère B utilisateur ID = 1234 Boom!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top