Sida 1 av 3

Kört fast i C#

Postat: 17 juni 2009, 21:59:16
av Gildebrand
Hejsan!
Ni kanske minns att jag tidigare sökte ett styrsystem för projektorer och kringutrustning. Jag hittade inget som jag gillade så det vart till att koda eget istället. Och nu har jag stött på problem.

först koden, sen problemet

COM.CS

Kod: Markera allt

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using System.Threading;

namespace WindowsFormsApplication1
{
    class com
    {
        public void Main(string[] args)
        {
            ThreadStart tsHello = new ThreadStart(Hello);
            ThreadStart tsWorld = new ThreadStart(World);

            Thread tHello = new Thread(tsHello);
            Thread tWorld = new Thread(tsWorld);

            tHello.Start();
            tWorld.Start();

            tHello.Join();
            tWorld.Join();
        }

        public void Hello()
        {
            SerialPort port = new SerialPort(
            "COM1", 9600, Parity.None, 8, StopBits.One);

            port.Open();
            port.Write("Hello");
            port.Write(new byte[] { 0x0A, 0xE2, 0xFF }, 0, 3);

            Thread.Sleep(2000);

            port.Write("Tjosilosan");
            port.Write(new byte[] { 0x0A, 0xE2, 0xFF }, 0, 3);
            port.Close();
        }
        public void World()
        {
            SerialPort port = new SerialPort(
            "COM1", 9600, Parity.None, 8, StopBits.One);

            port.Open();
            port.Write("World");
            port.Write(new byte[] { 0x0A, 0xE2, 0xFF }, 0, 3);
            port.Close();
        }
    }
}
och Form1.CS

Kod: Markera allt

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        com myCom = new com();

        public void Main(string[] args)
        {
            ThreadStart tsHello = new ThreadStart(myCom.Hello);
            ThreadStart tsWorld = new ThreadStart(myCom.World);

            Thread tHello = new Thread(tsHello);
            Thread tWorld = new Thread(tsWorld);

            tHello.Start();
            tWorld.Start();

            tHello.Join();
            tWorld.Join();
        }

        public Form1()
        {
            InitializeComponent();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            myCom.Hello();
            myCom.World();
        }

    }
}
Som ni ser finns det i com.cs två klasser. Klassen Hello skickar först ut "Hello" på COM1, för att sedan, 2 sekunder senare skicka ut "Tjosilosan" på samma port. Så långt funkar det bra.

Klassen World skickar bara ut "World" på COM1. Den funkar också finfint.

Men om jag nu kör båda samtidigt, alltså det som händer när jag trycker på button4, då fryser thread.freeze alltihop så att det som kommer in i hyperterminal blir

Kod: Markera allt

Hello
               â Tjosilosan
                               â World
                                         â
Mellan att Hello och Tjosilosan dyker upp går det alltså två sekunder, och World kommer direkt efter Tjosilosan.

Det är alltså inte så jag vill ha det, jag vill inte att World ska vänta med att skickas, utan den ska komma in samtidigt som Hello, och sen, 2 sekunder senare dyker Tjosilosan upp.

Jag försökte lösa det med hjälp av multithreading, men utan någon vidare lycka. Jag tänkte att då skulle thread.freeze bara frysa Hello, och inte World, men så är inte fallet.

Re: Kört fast i C#

Postat: 17 juni 2009, 22:28:48
av johano
Tror du behöver göra Close() *innan* du anropar Thread.Sleep i Hello-tråden.

/johan

Re: Kört fast i C#

Postat: 17 juni 2009, 23:35:34
av Gildebrand
Det har jag provat. Var visserligen tvungen att öppna den igen efter sleep, men det borde inte göra någon skillnad.

Funkar inte ivarjefall.

Re: Kört fast i C#

Postat: 18 juni 2009, 08:11:38
av Nerre
Det kan väl inte vara det smartaste att ha flera olika grejer som samtidigt ska pilla på samma serieport? Serieporten är ju en resurs som inte har några rutiner för att "delas".


Skriv hanteringen av serieporten separat, i huvudprogrammet, kanske rentav interruptstyrt, och låt dina klasser ställa sin text "i kö" hos den funktionen (eventuellt tillsammans med nån tidskod).

Re: Kört fast i C#

Postat: 18 juni 2009, 08:33:03
av bos
Nu kan jag inte C#, men eftersom du i var sin klass skapar en ny instans till din serieport innebär det att du får två separata hanterare som du sen pillar på i tid och otid i var sin tråd. Det är Fult, Felt och Dumt. Skapa *ett* handle till serieporten och använd detta globalt genom en wrapper och en kö.

Ungefär såhär (pseudokod):

Kod: Markera allt

serialhandle = SerialPort();
serialinhibit = 0;

function write_to_serial(text) {
    while (serialinhibit) {
       // evig paus tills serieporten blir fri
    }
    serialinhibit = 1;
    
    ...kod för att skriva till serieporten...
    ...vars handle finns i 'serialhandle'...

    serialinhibit = 0;
}

void Hello() {
   write_to_serial("Hello");
}

void World() {
   write_to_serial("World");
}

function main() {
   thread_start(Hello);
   thread_start(World);
}

Re: Kört fast i C#

Postat: 18 juni 2009, 11:28:48
av Gildebrand
Man tackar så mycket :) Ska prova det. Men borde inte Thread.Start ligga först?
Tänkte att jag kunde använda mig utav funktionen SerialPort som finns i Visual C# 2008.

Trodde det bara skulle gå att skriva SerialPort1.Write(Hej); men det gillade den inte

Re: Kört fast i C#

Postat: 18 juni 2009, 12:10:33
av bos
> Men borde inte Thread.Start ligga först?

Hur ska jag veta det? Jag kan som sagt inte C#. Jag pratar generellt om hur man ska bete sig med trådar och delade resurser.

> Tänkte att jag kunde (...)
> Trodde det bara (...)

Tittade du i C#-referensen efteråt för att se varför det inte gick?

Re: Kört fast i C#

Postat: 18 juni 2009, 12:15:48
av sodjan
> ...men det gillade den inte


"Gillade inte" är en fullständigt värdelös beskrivning av vad som (eller som inte) hände !

Re: Kört fast i C#

Postat: 18 juni 2009, 12:26:13
av Gildebrand
Sorry, för att jag inte berättade lite mer. Den sa att Hej does not appear in the current context, men det löste sig när jag la till skrev ("Hej") istället för (Hej).

Det borde väl bli samma sak som bos skrev innan i sitt kodexempel, bara utan all extra kod. serialport1 pekar ju på en funktion som finns inbäddad i programmet, och write_to_serial pekar på en funktion som man skapat.

Nu har jag SerialPort1 i Form1.cs, och vill kunna anropa den funktionen från com.cs.
Hur gör jag för att com.cs ska hitta SerialPort1 som ligger i form1.cs?

Re: Kört fast i C#

Postat: 18 juni 2009, 12:58:22
av bos
> det löste sig när jag la till skrev ("Hej") istället för (Hej).

Jag hoppas du förstår varför.

> write_to_serial pekar på en funktion som man skapat.

Vadå "pekar på en funktion"? write_to_serial() i min pseudokod *är* en funktion. Anropar du en funktion till i funktionen, eller vad menar du?

Re: Kört fast i C#

Postat: 18 juni 2009, 13:03:40
av Gildebrand
Oj, vart hel fel där.

Men har du nån idé om hur jag får com.cs att hitta SerialPort1 i form1.cs?

Re: Kört fast i C#

Postat: 18 juni 2009, 13:17:29
av bos
"extern", "include", "import", "external functions" är sökord jag skulle kolla efter i manualen.

Re: Kört fast i C#

Postat: 18 juni 2009, 13:19:10
av Icecap
När jag skriver C++ i Borland C Builder kommer man åt funktioner på andra form vid att skriva Formx->Önskat_Funktion osv.

Re: Kört fast i C#

Postat: 18 juni 2009, 13:32:21
av perra_e
Gildebrand skrev:Oj, vart hel fel där.

Men har du nån idé om hur jag får com.cs att hitta SerialPort1 i form1.cs?
Är det av någon speciell anledning du valt att lägga SerialPort1 i formuläret? Den om något borde väl ligga i klassen för att hantera kommunikationen.

Re: Kört fast i C#

Postat: 18 juni 2009, 14:05:18
av Gildebrand
Bos, vart kan jag läsa mer om det som du skrev om tidigare i ditt exempel? funkade inte direkt rakt av men det verkar vara en bra idé att prova.

Funderade lite på en grej, när jag klickar på knappen för klassen Hello och World, så fryser hela programmet i 2 sekunder. Så ska det väl inte vara? har jag inte gjort fel med trådarna nånstans då?