2010-05-19 18 views
1

J'essaye d'écrire un programme comme un compilateur. Dans ce cas je dois simuler ces codes de SQLPL (celui-ci peut être juste par exemple). Par exemple dans l'invite de commande je veux faire ces:comment éviter la condition de blocage

c:\> sqlplus 
.... 
Enter User-Name:(here we must enter username) xxxx 
Enter password:(same up)yyyyy 
... 
sql>(now I want to send my sql command to shell)prompt "rima"; 
"rima" [<-output] 
sql> prompt "xxxx" 
sql> exit 

très simple. Je essayer d'utiliser ce code:

ProcessStartInfo psi = new ProcessStartInfo(
@"sqlplus"); 
psi.UseShellExecute = false; 
psi.CreateNoWindow = true; 
psi.RedirectStandardInput = true; 
psi.RedirectStandardOutput = true; 
//psi.RedirectStandardError = true; 
Process process = new Process(); 
process.StartInfo = psi; 
bool started = process.Start(); 
if (started) 
{ 
process.StandardInput.WriteLine("user/password"); 
process.StandardInput.Flush(); 
string ret = process.StandardOutput.ReadLine(); // <-- stalls here 
System.Console.WriteLine("sqlplus says :" + ret + "\"."); 
} 

je trouve qu'il forme here mais si vous lisez ce code a un problème! DEADLOCK Problème de condition! C'est la deuxième fois que je pose ma question, chaque fois que mes connaissances grandissent, mais je n'arrive pas à comprendre comment je peux enfin résoudre mon problème !!!

Alors, je vous embrasse avec bonté, aidez-moi, ce processus n'est pas clair pour moi. Quelqu'un peut-il me donner un code qui gère mon problème? Déjà je regarde tous les codes, aussi j'essaie d'utiliser ProcessRunner que dans mon dernier post quelqu'un m'offre, mais je ne peux pas l'utiliser aussi, je reçois une erreur.

J'espère que par premier exemple, vous trouvez ce que je veux, et résoudre le second problème de code ...
J'utilise C# pour la mise en œuvre, aussi mon DB est Oracle
Je ne veux pas près sqlplus pour chaque connexion car il faut du temps pour se reconnecter.

Répondre

0

Vous approchez ne fonctionne pas pour cet exemple à mon avis. Vous avez écrit:

Entrez l'utilisateur Nom: (ici il faut entrer le nom d'utilisateur) xxxx
Entrez le mot de passe: (même jusqu'à) yyyyy

Il semble que il n'y a pas newline impliqué . Puisque vous vous connectez à StandardOutput, qui est tamponné il sera seulement vidé quand un caractère de nouvelle ligne apparaît ou un flush() est appelé directement. Ce n'est probablement pas le cas (cela devrait se produire dans sqlplus).

Aussi longtemps que vous ne pouvez pas changer sqlplus et insérer un flush ou un retour à la ligne là, une lecture synchrone ne vous aidera pas du tout. Essayez de communiquer asynchrone, comme:

process.OutputDataReceived += OnOutputDataReceived; 
process.Start(); 
process.BeginOutputReadLine(); 
// ... more missing code here ... 

Mais cette approche est beaucoup plus complexe ...

+0

nous pouvons également obtenir l'utilisateur et passer comme xxxx/yyyyy à sqlplus. dans ce cas, quelle est votre idée? – Amir

+0

Envoyer n'est pas un problème, vous allez envoyer un retour à la ligne après le nom d'utilisateur/mot de passe. Mais recevoir est votre problème. à mon humble avis, il faut aller avec une solution asynchrone pour savoir quelle entrée a été demandée et quelles réponses vous avez – tanascius