일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 정처기
- 정처기 실기
- C#
- MFC
- C# sprintf
- MariaDB
- HeidiSQL
- Telerik
- POST
- WinForms
- 정보처리기사
- c# 클로저
- UI
- create
- wss 파싱
- 정보처리기사 실기
- 프로토타입
- IndexOutOfRangeException
- Git
- System.IndexOutOfRangeException
- postgresql
- url파싱
- c# for
- url 파싱
- multipart/form-data
- VisualStudio2019
- drop
- git commit vi
- restapi
- show
- Today
- Total
달짱달짱
[C#] 인덱스 벗어남 오류 : 클로져 (Closure) 본문
for 문을 이용하여 아래와 같은 코드를 실행 시켰을 때, "System.IndexOutOfRangeException: '인덱스가 배열 범위를 벗어났습니다" 오류가 발생하였다. 해당 오류는 배열의 인덱스 범위를 벗어났을 때 발생하는 오류였다.
for(int i=0; i<arr.Length; i++)
{
Task.Run(() => MainTask(arr[i]));
}
하지만, 다른 언어에서는 위와 같이 for 문 안에서 다른 함수를 호출하였을 때 해당 오류가 나지않는다. 확인해보니 arr.length 는 2여서 i =0, i=1 일때만 타야하는데 arr[2] 일때도 MainTask 를 호출하도록 하고 있었다. 따라서 할당되지 않은 arr[2] 를 인자로 넘겨주려니 인덱스 범위를 벗어났다는 오류가 발생한 것이다.
관련하여 검색해보니 이는 c# 의 클로저로 인한 오류였다. 클로저는 외부 변수나 필드와 같은 '환경'을 저장하고 있는 함수를 뜻한다. C# 에서는 람다식을 사용하여 해당 내용을 전달 할 때, 외부의 변수나 필드를 사용하는 경우 Closure 처리가 된다.
Task.Run(() => MainTask(arr[i])); 코드는 람다식을 사용하여 MainTask를 비동기로 호출하는 부분이다. 하지만 클로저로 인해 문제가 발생한다.
반복문의 for 루프에서 i는 계속 증가하며 MainTask를 호출할 때 i의 값도 변하게 된다. 따라서 비동기 호출인 Task.Run에 의해 MainTask가 실행될 때, 이미 for 루프가 종료된 후의 i 값이 사용되게 된다.
예를 들어, arr.Length가 2일 경우 i는 0과 1까지 증가한다. 그리고 MainTask를 호출할 때 람다식이 Task.Run(() => MainTask(arr[i])) 호출 이후에 실행될 수 있으며, 이때 i의 최종 값인 2가 사용된다. 그러나 arr 배열의 인덱스는 0부터 시작하므로 deviceInfos[2]는 실제로는 없는 인덱스이다. 따라서 오류가 발생할 수 있다.
이러한 문제를 해결하기 위해서는 클로저의 동작을 피하는 방법을 사용해야 한다. 예를 들어, i의 값을 람다식의 인자로 넘겨주어 아래와 같은 방법으로 해결하였다.
for(int i=0; i<arr.Length; i++)
{
int index = i;
Task.Run(() => MainTask(arr[index]));
}
'C#' 카테고리의 다른 글
[C#] sprintf 처럼 형식화 된 데이터 사용 하기 (0) | 2023.07.12 |
---|---|
[C#/WinForms] Telerik TextBox 숫자만 입력되도록 하기 (0) | 2022.01.13 |
[C#/Winforms] Telerik 테마 변경 하기 (0) | 2021.12.30 |
[C#/WinForms] Metro Framework 사용 방법 (0) | 2021.09.15 |
[C#/WinForms] WinForms 프로젝트 열기 (0) | 2021.09.14 |