---
title: "Förslag på timeout funktion?"
type: "forum-thread"
url: "https://www.webforum.nu/amne/dotnet/57724-förslag-på-timeout-funktion"
topic: ".NET"
topic_url: "https://www.webforum.nu/amne/dotnet"
author: "Nickemannen"
published: "2002-11-01T11:48:03.000Z"
updated: "2002-11-08T19:17:29.000Z"
replies: 31
views: 712
page: 1
pages: 2
language: "sv-SE"
site: "webForum — webforum.nu"
rights: "Upphovsrätten till varje inlägg tillhör dess författare."
attribution: "Citera som: webForum, https://www.webforum.nu/amne/dotnet/57724-förslag-på-timeout-funktion"
---

# Förslag på timeout funktion?

_Sida 1 av 2._

## #1 — Nickemannen, 2002-11-01T11:48Z

Någon som har något förslag på hur man kan göra
när man försöker göra något men att den grejen inte får ta 
för lång tid
så att man kan skriva att 

funktionen timed-out ungefär ?

Permalänk: https://www.webforum.nu/p/57724

## #2 — renholm, 2002-11-01T12:14Z

Du tänker på ditt Half-life Server Stat projekt igen? :)

I så fall letar jag efter samma sak, en grej som sätter stop för om det tar för lång tid eller om inte servern hittas.

Permalänk: https://www.webforum.nu/p/842308

## #3 — Nickemannen, 2002-11-01T12:16Z

jepp, men det borde ju att göra en while loop med timer.

men det kanske finns något bättre

Permalänk: https://www.webforum.nu/p/842309

## #4 — fredrik, 2002-11-01T12:18Z

Kan du inte lägga anropet på en tråd, sen kan du kolla med ex. en timer (el. annan funktion) om det går för lång tid och i så fall så stoppar du bara tråden?

Permalänk: https://www.webforum.nu/p/842311

## #5 — Nickemannen, 2002-11-01T12:18Z

hittade denna i PHP men det borde gå att göra samma med

.NET

        $starttime=$this-\>timenow();
        do {
            $serverdata.=fgetc($cssocket);
            $serverdatalen++;
            $socketstatus=socket_get_status($cssocket);
            if ($this-\>timenow()\>($starttime+$waittime)) {
                $this-\>errmsg="Connection timed out";
                fclose($cssocket);
                return "";
            }
        } while ($socketstatus\["unread_bytes"\] );

Permalänk: https://www.webforum.nu/p/842313

## #6 — Nickemannen, 2002-11-01T12:19Z

hur menar du fredrik?

har du lite kod så man fattar bättre =

Permalänk: https://www.webforum.nu/p/842314

## #7 — niko, 2002-11-01T13:50Z

En ful och  primitiv trådvariant utan felhantering kan kanske se ut så här:

```
private Boolean bAllDone;
private long lTimeOut=2000; //2 sekunder t.ex ..

private void minTradStart() //Trådfunktion
	{
		// Gör nåt tidskrävande här.
		bAllDone=true;
	}

// Huvudprogram.
bAllDone=false;
Thread t = new Thread(new ThreadStart(minTradStart));
t.Name = "mintrad"
t.Start();
Thread.Sleep(lTimeOut); //Egentligen kan man göra nåt nyttigt här ..
if(bAllDone) //Blev tråden färdig innan time-outen?
{
	//Funktionen timade inte ut.
}
else
{
	//Funktionen timade ut.
}
```

Permalänk: https://www.webforum.nu/p/842382

## #8 — Nickemannen, 2002-11-01T14:01Z

Tack

Permalänk: https://www.webforum.nu/p/842386

## #9 — Nickemannen, 2002-11-01T14:25Z

hmm, man kan inte skicka info med 

Thread tThread = new Thread(new ThreadStart(getserverinfo(strIP,strPort)));

Då frågar den efter method name
det är bara
Thread tThread = new Thread(new ThreadStart(getserverinfo));

som fungerar :(

Permalänk: https://www.webforum.nu/p/842402

## #10 — Nickemannen, 2002-11-01T14:35Z

hmm, jag fick göra strängarna public

Permalänk: https://www.webforum.nu/p/842414

## #11 — Nickemannen, 2002-11-01T14:35Z

nu fungerar allt tack!

Permalänk: https://www.webforum.nu/p/842415

## #12 — niko, 2002-11-01T14:40Z

Ett bra sätt om du vill skicka med parametrar är annars att "kapsla in" trådfunktionen i en klass:

```
public class ServerInfo {

private string _ip = "";
private int _port = 0;

public ServerInfo(string ip, int port) {
_ip = ip;
_port = port;
}

public void minTradStart() //Trådfunktion
	{
		// Använd _ip och _port här.
		bAllDone=true;
	}
}

//Huvudprogram

ServerInfo s=new ServerInfo(strIP,strPort)
Thread t = new Thread(new ThreadStart(ServerInfo.minTradStart));
t.Name = "mintrad"
t.Start();
```

Permalänk: https://www.webforum.nu/p/842419

## #13 — developer, 2002-11-01T14:59Z

Att starta trådar är något man bör undvika, en mycket bättre metod är att använda asynkrona anrop.

Jag vet inte riktigt vad du vill göra, så det är svårt att ge ett passande exempel. Men anta att du vill koppla upp en socket, då är rätt metdo socket.BeginConnect() istället för socket.Connect(). BeginConnect() kommer då returnera direkt, sedan får du en callback-funktion när uppkopplingen är klar (eller gick fel).

Permalänk: https://www.webforum.nu/p/842436

## #14 — Nickemannen, 2002-11-01T15:11Z

Det är så att jag använder
UdpClient för att komma åt information från HL-Servrar

och så skickar jag lite kod och skall få ett svar
men om jag inte får det svaret så står allt stilla ett bra tag 
tills hela sidan blir error

Vad får man för callback ?

Permalänk: https://www.webforum.nu/p/842447

## #15 — developer, 2002-11-01T16:09Z

Det som i grunden används av UdpClient är en Socket, som har metoder för asynkron använding. UdpClient är dessvärre lite tråkig eftersom den inte stöder asynkron använding.

Lyckligtvis exponerar den socketen som används som en protected property. Jag drog nytta av det och ärvde UdpClient till en klass AdvancedUdpClient, som lägger till BeginReceive/EndReceive. Min ärvda klass bara skickar vidare anropen till Socket:en. Jag har som du ser bara gjort Receive, så resten (Send/Connect) får du klura ut själv :).

Därtill ett litet testprogram, som använder AdvancedUdpClient. All kod är garanterat **otestad**, så du får väl provköra och se hur det verkar ;).

```
using System;
using System.IO;
using System.Net.Sockets;
using System.Net;

class UdpTest {
	/// <summary>
	/// Istället för UdpClient för att kunna använda asynkront
	/// </summary>
	AdvancedUdpClient Udp;

	/// <summary>
	/// Buffer där Receive lagrar data
	/// </summary>
	byte[] receiveBuffer = new Byte[10000];

	/// <summary>
	/// Callback som anropas när Receive är klar (lyckad eller misslyckad)
	/// </summary>
	AsyncCallback callbackOnReceive = new AsyncCallback(OnReceive);

	/// <summary>
	/// Denna kommer anropas när vi får något på socket, eller när
	/// något fick fel med att ta emot. I vilket fall ska vi ropa
	/// på EndReceive. Om EndReceive kastar exception gick det dåligt,
	/// annars gick det bra och returvärdet är så många bytes
	/// som finns i bufferten.
	/// </summary>
	/// <param name="ar"></param>
	static void OnReceive(IAsyncResult ar) {
		UdpTest udpTest =  (UdpTest) ar.AsyncState;
		AdvancedUdpClient Udp = udpTest.Udp;
		try {
			int size = Udp.EndReceive(ar);
			// vi har nu tagit emot <size> bytes, och dessa ligger först i
			// udpTest.receiveBuffer
			Console.WriteLine("fick " + size.ToString() + " bytes");
		}
		catch (IOException ex) {
			Console.WriteLine("fel: " + ex);
		}
	}

	void Test() {
		Udp = new AdvancedUdpClient(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 1234));
		Udp.BeginReceive(receiveBuffer, 0, receiveBuffer.Length, SocketFlags.None, callbackOnReceive, Udp);
	}

	static void Main() {
		// kör testprogrammet
		UdpTest udpTest = new UdpTest();
		udpTest.Test();

		// vänta på <enter> så vi inte avslutar direkt
		Console.ReadLine();
	}
}

/// <summary>
/// Utökar UdpClient så den kan användas asynkront. Bara Receive
/// är gjord.
/// </summary>
public sealed class AdvancedUdpClient : UdpClient {
	public AdvancedUdpClient(IPEndPoint ep) : base(ep) {
	}

	public IAsyncResult BeginReceive(byte[] buffer,
							int offset, int size, SocketFlags socketFlags,
							AsyncCallback callback,
							object state) {
		return Client.BeginReceive(buffer, offset, size, socketFlags, callback, state);
	}

	public int EndReceive(IAsyncResult asyncResult) {
		return Client.EndReceive(asyncResult);
	}
}
```

Permalänk: https://www.webforum.nu/p/842483

## #16 — Nickemannen, 2002-11-01T16:12Z

tack skall titta på det

hinner dock inte nu

Permalänk: https://www.webforum.nu/p/842486

## #17 — niko, 2002-11-01T16:20Z

Fast om jag tolkar Nickemannen rätt så tänker han köra koden i en ASP.NET-sida?

> **Nickemannen skrev:**
>
> tills hela sidan blir error

Då är väl inte asynkrona anrop så lyckade eftersom sidan kan ha  terminerat innan callbacken kommer?

Jag hade nog använt trådar och sedan använt **Join** och inväntat trådarna med en lämpligt vald timeout: 

<http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemthreadingthreadclassjointopic3.asp>

Annat bra exempel:

<http://www.c-sharpcorner.com/Code/2002/Mar/MultiThreadPortScannerTLam.asp>

Permalänk: https://www.webforum.nu/p/842492

## #18 — developer, 2002-11-01T17:07Z

> **niko skrev:**
>
> Fast om jag tolkar Nickemannen rätt så tänker han köra koden i en ASP.NET-sida?
> ...
> Då är väl inte asynkrona anrop så lyckade eftersom sidan kan ha  terminerat innan callbacken kommer?

Sant. Använd isåfall en asynkron http handler för att klara detta, se <http://www.codeguru.com/net_asp/Asynchronous.html>

> **niko skrev:**
>
> Jag hade nog använt trådar och sedan använt **Join** och inväntat trådarna med en lämpligt vald timeout:

Nu vet jag inte om prestanda är något problem här. Det kanske det finns CPU-cykler så det räcker och blir över, och det kanske är ok att skapa trådar. Men eftersom jag sett så många fall där man skapar trådar hej vilt och sedan inte förstår varför applikationen inte presterar bra känner jag mig manad att göra ett inlägg om detta.

Det är dåligt att skapa trådar som inte behövs. Anta att 10 personer tittar på sidan ungefär samtidigt, och att det tar 5 sekunder att få svar på udp-receive. Då skapar du ungefär 50 trådar - det är många trådar i en och samma process. Det är inte ens säkert att du får göra det, man kan begränsa sådant, eftersom många trådar har en enormt negativ påverkan på operativsystemets prestanda. Medan min asynkrona applikation körs på en och samma tråd och gör det som behöver göras, måste operativsystemet in och context-switcha (byta tråd) 50 gånger för din applikation. Det innebär att spara undan CPU-state och switcha user- och kernel-mode stackarna. Lägg på lite last så kommer ditt program inte göra något annat än att byta trådar. Värre är att du kommer minska chansen att få cache-träffar, vilket leder till fler sidfel för att hämta data från RAM. Det är dessutom dyrt att skapa en tråd.

Asynkron kod använder en trådpool genom "I/O completion ports" som stöds av Win32, lite svårare att använda, men mycket bättre. Dålig trådhantering är en vanlig orsak till dålig prestanda, och ofta är det komplicerat att ändra designen i efterhand.

Permalänk: https://www.webforum.nu/p/842516

## #19 — renholm, 2002-11-01T19:39Z

Kan lägga till en liten sak, för att slippa att det görs en Udp request varje gång så kan man cacha datan i t.ex 5 minuter beroende på hur aktuellt värdet måste vara.

Permalänk: https://www.webforum.nu/p/842598

## #20 — niko, 2002-11-02T11:19Z

developer\>\>

Håller med om att man inte ska skapa trådar i onödan. Fast i detta fallet ser jag även vissa fördelar.

1\. Snygg och enkel hantering av timeout-kriteriet. (Vilket egentligen var huvudfrågan här om jag inte minns fel? ;) )

```

for ( i = 0; i < MAX_THREADS; i ++ ) {
	lThreads[i] = new Thread( new ThreadStart( minTradFunktion) );
	lThreads[i].Start();
}

for ( i = 0; i < lThreads.Length; i ++ )
	if lThreads[i].Join(timeOut)
		//Tråd nr i blev färdig innan time-outen. Gör något ..
	else
		//Tråd nr i blev INTE färdig innan time-outen. Döda tråden ..
```

2\. Koden skalar automatiskt till flera processorer. En singeltrådad version med asynkrona anrop kommer att köa alla callbackanrop på samma processor. (Eller är jag ute och cyklar?)

Och slutligen, som renholm påpekar, om man får prestandaproblem så finns ju alltid output-cachning .. Om tio personer tittar på sidan samtidigt så är det knappast troligt att finns någon anledning att köra koden tio ggr? Så tidskritiskt lär det sällan vara ..

Permalänk: https://www.webforum.nu/p/842819

---

Tråden på webben: https://www.webforum.nu/amne/dotnet/57724-förslag-på-timeout-funktion  
Nästa sida: https://www.webforum.nu/amne/dotnet/57724-förslag-på-timeout-funktion/page2.md
