2015-10-07 4 views
13

मैं एक विधि भागो जो स्क्रीन पर चित्रों को स्थानांतरित करने के माना जाता है के साथ एक कुत्ता वर्ग है:रनिंग तरीके इसके साथ ही

public bool Run() 
{ 
    Point p = PictureBoxDog.Location; 

    while(p.X < 530) 
    { 
     int movement = Randomizer.Next(0, 3); 
     p.X += movement; 
     PictureBoxDog.Location = p; 
    } 

    if (Location == 4) //Incomplete section. 
     return true; 
    else 
     return false; 
} 

इस विधि है, जिसमें 4 कुत्ते ऑब्जेक्ट का निर्माण होगा एक बटन क्लिक करें घटना और से कहा जाता है प्रत्येक ऑब्जेक्ट रन विधि को कॉल करता है:

private void button1_Click(object sender, EventArgs e) 
{ 
    Dog dog1 = new Dog(pictureDog1); 
    Dog dog2 = new Dog(pictureDog2); 
    Dog dog3 = new Dog(pictureDog3); 
    Dog dog4 = new Dog(pictureDog4); 

    dog1.Run(); 
    dog2.Run(); 
    dog3.Run(); 
    dog4.Run(); 
} 

समस्या यह है कि प्रत्येक विधि एक-एक करके निष्पादित होती है, एक साथ नहीं। मैं चाहता हूं कि प्रत्येक विधि एक ही समय में चलें। अगर मैं थोड़ी देर के वक्तव्य को हटा देता हूं, तो सभी विधियां एक ही समय में निष्पादित होती हैं, लेकिन थोड़ी देर के साथ, वे एक के बाद एक निष्पादित करते हैं। इस समस्या को ठीक करने के तरीके पर कोई सुझाव बहुत सराहना की जाती है। जबकि पाश के बिना चलाने के लिए विधि:

public bool Run() //Dog1.Run() 
{ 
    Point p = PictureBoxDog.Location; 

    int movement = Randomizer.Next(0, 30); 
    //Location += movement; 

    p.X += movement; 
    PictureBoxDog.Location = p; 

    if (Location == 4) //Incomplete code. 
    return true; 
    else 
    return false; 
} 
+2

एक टाइमर जोड़ें और वहां से विधियों को कॉल करें। तब आपको थ्रेड के साथ गड़बड़ नहीं करनी पड़ेगी, जो यूआई तत्वों के साथ समस्याएं पैदा करती है यदि आप नहीं जानते कि आप क्या कर रहे हैं। –

उत्तर

4

इस

Dispatcher.BeginInvoke((Action) (() => 
{ 
    dog1.Run(); 
})); 
Dispatcher.BeginInvoke((Action) (() => 
{ 
    dog2.Run(); 
})); 
Dispatcher.BeginInvoke((Action) (() => 
{ 
    dog3.Run(); 
})); 
Dispatcher.BeginInvoke((Action) (() => 
{ 
    dog4.Run(); 
})); 

की कोशिश करो और जबकि के लिए लूप रूप में अच्छी तरह का उपयोग इस

Dispatcher.BeginInvoke((Action) (() => 
{ 
    while(p.X < 530) 
    { 
     int movement = Randomizer.Next(0, 3); 
     p.X += movement; 
     PictureBoxDog.Location = p; 
    } 
})); 

BeginInvoke अतुल्यकालिक है; इसलिए, इसे कॉल करने के बाद तुरंत कॉलिंग ऑब्जेक्ट पर नियंत्रण लौटाता है। BeginInvoke एक डिस्पैचरऑपरेशन ऑब्जेक्ट देता है जिसका उपयोग प्रतिनिधि के साथ बातचीत करने के लिए किया जा सकता है जब प्रतिनिधि ईवेंट कतार में होता है। BeginInvoke द्वारा लौटाई गई डिस्पैचरऑपरेशन ऑब्जेक्ट को निर्दिष्ट प्रतिनिधि

+2

यह लूप समस्या को हल नहीं करता है। –

+0

यह कहता है कि मुझे डिस्पैचर का उपयोग करने के लिए ऑब्जेक्ट संदर्भ की आवश्यकता है। मुझे क्या करना चाहिए? क्षमा करें, मैं इस सामान के साथ बहुत अनुभवी नहीं हूँ। – grammer

+1

प्रश्न में पिक्चरबॉक्स शामिल हैं, जो WinForms हैं। आप डिस्पैचर के बारे में बात कर रहे हैं, जो डब्ल्यूपीएफ है - मुझे संदेह है कि यह WinForms इवेंट लूप के साथ अच्छा खेलेंगे। –

13

एनीमेशन और विनफॉर्म आमतौर पर सीधा नहीं है, के साथ बातचीत करने के कई तरीकों से उपयोग किया जा सकता है। आम तौर पर कौन से प्रोग्रामर एक गेम लूप स्थापित करते हैं। एक गेम लूप तीन चीजें करता है - उपयोगकर्ता इनपुट प्राप्त करें, sprites की नई स्थिति अपडेट करें, और उसके बाद स्क्रीन पर sprites आकर्षित करें।

using System.Threading; 

public partial class Form1 
{ 
    private Timer _timer; 
    private Dog _dog1, _dog2, _dog3, _dog4; 

    public void InitializeComponent() 
    { 
     SetupDogs(); 

     // Every quarter of a second, run the function GameLoop 
     _timer = new Timer(GameLoop, null, 
     TimeSpan.FromSeconds(0.25), 
     TimeSpan.FromSeconds(0.25)); 
    } 

    private void SetupDogs() 
    { 
     _dog1 = new Dog(PictureBoxDog1); 
     _dog2 = new Dog(PictureBoxDog2); 
     _dog3 = new Dog(PictureBoxDog3); 
     _dog4 = new Dog(PictureBoxDog4); 

    } 

    public void GameLoop(object state) 
    { 
     GetUserInput(); 
     Update(); 
     Draw(); 
    } 

    public void GetUserInput() 
    { 
    // You don't need this now. But if you need to 
    // process user input later, you can do it here. 
    // 
    // e.g. if Last key 
    // pressed was arrow-left or 
    // arrow-right etc. 
    } 

    public void Update() 
    { 
    _dog1.Update(); 
    _dog2.Update(); 
    _dog3.Update(); 
    _dog4.Update(); 
    } 

    public void Draw() 
    { 
     // Draw on the main UI thread 
     Dispatcher.BeginInvoke(() => 
     { 
     _dog1.Draw(); 
     _dog2.Draw(); 
     _dog3.Draw(); 
     _dog4.Draw(); 
     }); 
    } 

} 

तब आपका कुत्ता वर्ग इस तरह दिखता है।

public class Dog 
{ 

    bool _isRunning = true; 

    Point Location { get; set; } 

    Point NextLocation { get; set; } 

    PictureBox PictureBoxDog { get; set; } 

    public Dog(PictureBox pictureBox) 
    { 
    PictureBoxDog = pictureBox; 

    Location = GetRandomLocation(); 

    NextLocation = GetRandomLocation(); 
    } 

    private Point GetRandomLocation() 
    { 
    var random = new Random(); 
    return new Point(random.Next(800), random.Next(800)); 
    } 

    public void Update() 
    { 
    // Calculates the new coordinates for a dog 

    // The dog starts from a random position, and is 
    // given a new random position to run towards. 

    // If the dog has arrived at the new random position, then 
    // give the dog a new random position to run to again 
    if (NextLocation.X == Location.X && NextLocation.Y == Location.Y) 
    { 
     NextLocation = GetRandomLocation(); 
    } 

    if (_isRunning) 
    { 
     // Move the dog closer to its destination 
     // dx and dy can be -1, 0, or 1 
     var dx = Math.Sign(NextLocation.X - Location.X); 
     var dy = Math.Sign(NextLocation.Y - Location.Y); 

     Location = new Point(Location.X + dx, Location.Y + dy); 
    } 
    } 

    public void Draw() 
    { 
    PictureBoxDog.Location = Location; 
    } 
} 
+0

इस दृष्टिकोण की तरह, लेकिन मैं 'रैंडम' उदाहरण का पुनः उपयोग करूँगा और फॉर्म/पिक्चर बॉक्स पर 'BeginInvoke' का उपयोग करके ड्राइंग कॉल प्रेषित करूंगा। – Gene

+0

अच्छा पिकअप! धन्यवाद! –

+0

आपकी मदद के लिए धन्यवाद, लेकिन यह मेरे लिए बहुत उन्नत लगता है। मैं वास्तव में इसका एहसास नहीं कर सकता। मैं सी # के साथ बहुत अनुभवी नहीं हूँ। – grammer

0

यह क्यों इस्तेमाल नहीं है: यह अपने स्थान हर घड़ी टिक्स Update, और फिर अपनी स्थिति को आकर्षित जरूरत है?

Task.Factory.StartNew(() => Parallel.ForEach<Dog>(Dogs, dog=> dog.run())); 

सही ढंग से इस निर्देश का उपयोग करने के लिए आपको कुत्ते की एक सूची बनाना चाहिए।

List<Dog> Dogs = new List<Dog>(); 
     Dogs.Add(dog1); 
     Dogs.Add(dog2); 
     Dogs.Add(dog3); 
     Dogs.Add(dog4); 
     Task.Factory.StartNew(() => Parallel.ForEach<Dog>(Dogs, dog => dog.Run())); 

आप सूची पसंद नहीं है:

Task.Factory.StartNew(() => dog1.Run()); 
Task.Factory.StartNew(() => dog2.Run()); 
Task.Factory.StartNew(() => dog3.Run()); 
Task.Factory.StartNew(() => dog4.Run()); 

एक अलग धागे से यूआई के साथ बातचीत करने के लिए, आप एक प्रतिनिधि और बुला Control.Invoke/BeginInvoke उपयोग करने के लिए की जरूरत है। आप यह जांच सकते हैं कि आपको InvokeRequired संपत्ति का उपयोग करके आमंत्रण कॉल करने की आवश्यकता है या नहीं। तो आपके मामले में:

if (PictureBoxDog.InvokeRequired){ 
PictureBoxDog.Invoke((MethodInvoker)(() => PictureBoxDog.location = p));} 
+0

इसके परिणामस्वरूप त्रुटियां हुईं। – grammer

+0

मैंने जवाब – Donald

+0

संपादित किया। इसके परिणामस्वरूप एक और त्रुटि संदेश हुआ: अतिरिक्त जानकारी: क्रॉस-थ्रेड ऑपरेशन मान्य नहीं है: – grammer

संबंधित मुद्दे