< Timer란 ? >

Timer는 일정한 시간 간격으로 코드를 실행할 때 사용된다. 예를 들어, 주기적으로 데이터를 새로고침하거나, 시간을 표시하는 데 사용할 수 있다.

C#에는 크게 세 가지 타입의 Timer가 있다.

  • System.Windows.Forms.Timer
  • System.Timers.Timer
  • System.Threading.Timer

 


[System.Windows.Forms.Timer]

이 Timer는 UI 스레드에서 동작한다. 따라서, UI 요소를 갱신하는데 유용하다. 하지만 오래 걸리는 작업을 처리하면 UI가 멈출 수 있다.

[매 초마다 현재 시간을 화면에 표시하는 코드]

using System;
using System.Timers;

class Program
{
    static void Main()
    {
        System.Timers.Timer myTimer = new System.Timers.Timer(2000); // 2초 간격으로 설정
        myTimer.Elapsed += OnTimedEvent; // 이벤트 핸들러 연결
        myTimer.Start(); // 타이머 시작

        Console.WriteLine("Press Enter to exit...");
        Console.ReadLine();
    }

    private static void OnTimedEvent(Object source, ElapsedEventArgs e)
    {
        Console.WriteLine("The Elapsed event was raised at {0}", e.SignalTime);
    }
}

위 코드는 2초마다 콘솔에 현재 시간을 출력한다. Elapsed 이벤트에 메소드를 연결하여 타이머가 경과할 때마다 실행된다.


[System.Threading.Timer]

이 Timer는 스레드 풀의 스레드에서 작업을 수행한다. 주로 백그라운드 작업에 적합하다.

using System;
using System.Threading;

class Program
{
    static int count = 0;

    static void Main()
    {
        TimerCallback callback = new TimerCallback(PrintMessage);
        Timer stateTimer = new Timer(callback, null, 0, 2000); // 2초 간격으로 설정

        Console.WriteLine("Press Enter to exit...");
        Console.ReadLine();
    }

    static void PrintMessage(object state)
    {
        count++; // 카운터 증가
        Console.WriteLine($"안녕하세요. {count}번째 윤태영입니다.");
    }
}

위 코드도 2초마다 메시지를 출력한다. 하지만 이 타이머는 스레드 풀의 스레드를 사용한다.

 

※ System.Threading.Timer와 System.Timers.Timer

둘 다 주기적으로 코드를 실행하는데 사용된다. 하지만 둘 사이에는 차이점이 있다.

무거운 작업이거나 높은 정밀도(빠른 간격의 정확한 타이밍)가 필요하면 System.Threading.Timer를 사용이 권장된다.
이벤트 기반으로 작업하거나 UI와 상호작용이 필요하다면 System.Timers.Timer이 권장된다.


[System.Windows.Forms.Timer] 

WinForms 애플리케이션에서 사용되는 Timer. UI 스레드에서 실행된다.

using System;
using System.Drawing;
using System.Windows.Forms;

namespace WinFormsApp4
{
    public partial class Form1 : Form
    {
        private System.Windows.Forms.Timer timer1;
        private int counter = 0;
        private Label greetingLabel;
        private Color[] colors = { Color.Red, Color.Orange, Color.Yellow, Color.Green, Color.Blue, Color.Indigo, Color.Violet };
        
        public Form1()
        {
            InitializeComponent();

            timer1 = new System.Windows.Forms.Timer();
            timer1.Tick += TimerEventProcessor;
            timer1.Interval = 2000; // 2초
            timer1.Start();
        }

        private void TimerEventProcessor(object sender, EventArgs e)
        {
            counter++;
            this.Text = "Counter: " + counter.ToString();

            //배경색 변경
            this.BackColor = colors[counter % colors.Length];
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            
            // 라벨을 생성하고 "안녕하세요!" 출력하기.
            greetingLabel = new Label();
            greetingLabel.Text = "안녕하세요!";
            greetingLabel.Location = new Point(350, 200); // 라벨의 위치 설정
            greetingLabel.AutoSize = true;

            // 라벨을 폼에 추가.
            this.Controls.Add(greetingLabel);
        }
    }
}
namespace WinFormsApp4
{
    partial class Form1
    {
        private System.ComponentModel.IContainer components = null;

        // 폼이 종료될 때 리소스를 정리하는 메서드
        // disposing 매개변수가 true이면 관리되는 리소스를 해제
        protected override void Dispose(bool disposing)
        {
            // disposing이 true이고, components가 null이 아니라면
            // components를 해제하여 메모리를 정리
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code


        private void InitializeComponent()
        {
            SuspendLayout();

            // Form1 설정
            // AutoScaleDimensions -> 폼의 크기를 조절하는데 사용되는 설정값
            AutoScaleDimensions = new SizeF(7F, 15F);
            //  폰트 크기에 맞춰 조절.
            AutoScaleMode = AutoScaleMode.Font;
            ClientSize = new Size(800, 450);
            Name = "Form1";
            Text = "Form1";
            // 폼이 로드될 때 실행할 이벤트 핸들러를 설정
            Load += new System.EventHandler(this.Form1_Load);

            ResumeLayout(false);
        }

        #endregion
    }
}

2초마다 폼의 배경색을 변경할 수 있도록 해보았다.

 

 

Reference : C#.NET 0.5년차~3년차(파트1)

https://www.inflearn.com/course/lecture?courseSlug=%EB%8B%B7%EB%84%B7-%EC%9C%88%ED%8F%BC-1&unitId=77894&tab=curriculum 

 

학습 페이지

 

www.inflearn.com

 

'C#' 카테고리의 다른 글

Indexers  (0) 2023.06.16
Thread Pool  (0) 2023.06.16
일반화 프로그래밍  (0) 2023.06.15
이벤트 생성/호출  (0) 2023.06.15
크로스 스레드  (0) 2023.06.15

< 일반화 프로그래밍이란? >

일반화 프로그래밍이란, 메서드나 클래스를 정의할 때 특정 타입이 아닌, 타입 파라미터를 사용하여 여러 타입에 대해 동작하는 코드를 작성하는 것이다.

일반화 프로그래밍을 상자에 비유하자면, 상자 안에는 무엇이든 넣을 수 있다. 과자도 넣을 수 있고, 책도 넣을 수 있다. 일반화 프로그래밍에서의 상자가 바로 '제네릭 클래스'나 '제네릭 메서드'다.

< 일반화 프로그래밍의 장점 >

  • 타입 안전(Type Safety) : 컴파일 시점에 타입 검사를 하기 때문에 런타임 오류를 줄일 수 있다.
  • 재사용성(Reusability) : 하나의 코드로 다양한 타입에 대응할 수 있으므로 코드 중복을 줄일 수 있다.
  • 성능 향상(Performance): 박싱(Boxing)과 언박싱(Unboxing)을 줄여 메모리와 CPU 사용량을 최적화한다.

 

[제네릭 클래스 만들기] 

public class MyBox<T>
{
    private T item;

    public void Put(T item)
    {
        this.item = item;
    }

    public T TakeOut()
    {
        return item;
    }
}

 

위의 예시에서 MyBox는 제네릭 클래스다. <T>는 타입 파라미터로, 어떤 타입이든 될 수 있다.

[제네릭 클래스 사용해보기] 

MyBox<string> stringBox = new MyBox<string>();
stringBox.Put("Hello, Generics!");
Console.WriteLine(stringBox.TakeOut()); // 출력: Hello, Generics!

MyBox<int> intBox = new MyBox<int>();
intBox.Put(123);
Console.WriteLine(intBox.TakeOut()); // 출력: 123

 

MyBox를 사용하여 문자열과 정수를 담는 상자를 만들었다.

[제네릭 메서드 만들기]

public class Utils
{
    public static void Swap<T>(ref T a, ref T b)
    {
        T temp = a;
        a = b;
        b = temp;
    }
}

 

Swap 메서드는 두 개의 값을 교환한다. 여기서도 타입 파라미터 <T>를 사용한다.

[제네릭 메서드 사용해보기]

int a = 5, b = 10;
Utils.Swap(ref a, ref b);
Console.WriteLine($"a: {a}, b: {b}"); // 출력: a: 10, b: 5

string x = "hello", y = "world";
Utils.Swap(ref x, ref y);
Console.WriteLine($"x: {x}, y: {y}"); // 출력: x: world, y: hello

 

숫자 뿐만 아니라 문자열도 바꿀 수 있다.


 

Reference : 이것이 C#이다

https://product.kyobobook.co.kr/detail/S000201856223

 

이것이 C#이다 | 박상현 - 교보문고

이것이 C#이다 | 전문가로 레벨업!C# 프로그래밍 완전 정복이 책은 C#의 기본, 고급 문법과 더불어 기초 클래스 라이브러리까지 다루고 있다. 총 22개 장으로, 앞서 배운 내용을 활용하면서 단계별

product.kyobobook.co.kr

 

'C#' 카테고리의 다른 글

Thread Pool  (0) 2023.06.16
Timer  (0) 2023.06.16
이벤트 생성/호출  (0) 2023.06.15
크로스 스레드  (0) 2023.06.15
스레드 문제점 해결  (0) 2023.06.14

< 이벤트란? >

이벤트(event)는 어떤 사건이 발생했을 때 통보를 받고 해당 사건에 대응하여 처리를 수행하는 프로그래밍 패턴이다. 예를 들어, 버튼 클릭, 키 입력, 타이머 만료 등과 같은 상황을 이벤트라고 할 수 있다. 이벤트는 특정 사건이 발생했을 때 델리게이트를 통해 해당 사건을 처리하는 메서드를 호출한다.

< 이벤트 생성하기 >

이벤트를 사용하기 위해서는 먼저 이벤트를 정의해야 한다.

이벤트를 정의할 때는 event 키워드를 사용한다.

public delegate void MyEventHandler(string message); // 델리게이트 정의
public event MyEventHandler MyEvent; // 이벤트 정의


< 이벤트 구독 및 처리하기 >

이벤트가 발생했을 때 실행할 메서드를 작성하고, 이 메서드를 이벤트에 연결한다. 이를 이벤트 구독(subscription)이라고 한다.

아래의 Form1과 Form2 코드가 있다.

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

namespace WindowsFormsApp2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.Show();
            form2.OnCount += MyCount;
        }

        int c = 0;

        //자식클래스가 보낸데이터 수신(구독)
        public void MyCount(int myCount)
        {
            c += myCount;
            label1.Text = c.ToString();
        }
        
    }
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp2
{
    public partial class Form2 : Form
    {
        public delegate void CountHandler(int addCount);
        public event CountHandler OnCount;

        public Form2()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //이 예제에서 매개변수로 int를 전달하지만.
            //개발자가 만든Class의 객체,string도 가능
            OnCount(1);
        }
    }
}

 

[Form2 (이벤트 생성자)]

먼저 Form2에서는 델리게이트를 정의한다. 이 델리게이트는 int형 매개변수를 받는 메서드를 참조한다.

델리게이트를 사용하여 이벤트를 정의한다. 이 이벤트는 Form2의 버튼이 클릭될 때 발생시킬 것이다.

public delegate void CountHandler(int addCount);

 

button1_Click 메서드에서는 이벤트를 발생시킨다. 이 예제에서는 1이라는 값을 매개변수로 전달한다.

public event CountHandler OnCount;

[Form1 (이벤트 구독자)]
Form1에서는 Form2의 인스턴스를 생성하고, Form2의 OnCount 이벤트에 대한 구독을 설정한다. 이때 Form1 내의 MyCount 메서드가 구독자로 동작한다.

private void button1_Click(object sender, EventArgs e)
{
    Form2 form2 = new Form2();
    form2.Show();
    form2.OnCount += MyCount;
}

 

MyCount 메서드는 Form2로부터 받은 값을 c에 더하고, 이를 레이블에 표시한다. 이 메서드는 Form2의 OnCount 이벤트에 의해 호출된다.

int c = 0;

public void MyCount(int myCount)
{
    c += myCount;
    label1.Text = c.ToString();
}

 

 

이렇게 Form2에서 발생한 이벤트가 Form1에서 처리된다. Form2의 버튼을 클릭할 때마다 Form1의 레이블에 표시되는 값이 증가한다. 이벤트를 사용함으로써 두 폼 사이에 느슨한 결합(loose coupling)을 유지할 수 있고, 코드의 유지 보수가 용이해진다.


Reference : https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/events/

 

Events - C# Programming Guide

Learn about events. Events enable a class or object to notify other classes or objects when something of interest occurs.

learn.microsoft.com

C#.NET 0.5년차~3년차(파트1)

※ 블로그에 있는 모든 강의와 책의 내용은 저작권자(출판사/저자,공동저자)에게 직접 허락을 받아 작성되었습니다.

https://www.inflearn.com/course/lecture?courseSlug=%EB%8B%B7%EB%84%B7-%EC%9C%88%ED%8F%BC-1&unitId=77892&tab=curriculum 

 

학습 페이지

 

www.inflearn.com

 

'C#' 카테고리의 다른 글

Timer  (0) 2023.06.16
일반화 프로그래밍  (0) 2023.06.15
크로스 스레드  (0) 2023.06.15
스레드 문제점 해결  (0) 2023.06.14
비동기, 동기  (0) 2023.06.14

< 크로스 스레드란 ? >

크로스 스레드 문제는 멀티 스레드 환경에서 발생한다. Form 컨트롤러를 생성한 UI 스레드 외에 다른 스레드가 컨트롤러에 직접 접근할 경우 발생하는 에러다. 이를 통해 개발자에게 스레드 문제가 있음을 알려준다.

이는 디버그 모드에서만 발생하며, Thread Safety를 보장하지 않는다. 크로스 스레드가 발생하면, Program이 실행되다가, OS 상황이 안좋아지면, 프로그램에 영향을 줄 수 있다.

< Thread Safety란? >

Thread Safety는 변수, 객체 또는 다른 공유 자원이 여러 스레드로부터 동시에 접근이 이루어져도 프로그램 실행에 문제가 없음을 의미한다. 즉, 공유 자원의 상태가 예상 가능하고 일관된 상태를 유지해야 한다.

< UI-Thread 외 다른 스레드에서 Controller를 안전하게 하는 방법 >

크로스 스레드 문제를 해결하기 위해 Invoke와 Delegate 조합 사용하여 동기적으로 UI 스레드에게 해당 함수를 호출하도록 요청할 수 있다. 이렇게 하면 UI 스레드가 컨트롤러를 안전하게 업데이트한다.(비동기로 할려면 BeginInvoke를 사용해도 된다.)

또 매게 변수가 없고 Return Type이 없는 것은 new Action을 통해서도 할 수 있다.

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

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        Thread thread2 = null;

        private void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                thread2 = new Thread(new ThreadStart(SendLogic));
                thread2.IsBackground = true;
                thread2.Priority = ThreadPriority.Normal;
                thread2.Start();
            }
            catch (Exception ex)
            {
                //에러 로그기록
            }
            
        }

        private void SendLogic()
        {
            try
            {

                this.Invoke(new Action(() =>
                {
                    label1.Text = "bb";
                    label2.Text = "bb";
                }));
//MethodInvoker를 사용하는 이유 : Invoke 메서드와 MethodInvoker를 사용하면 UI 스레드에서 코드를 안전하게 실행할 수 있기 때문
                Invoke((MethodInvoker)delegate {
                    label1.Text = "cc";
                    label2.Text = "cc";

                });
            }
            catch (Exception ex)
            {
                //에러 로그기록
            }

        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            try
            {
                if (thread2.IsAlive)
                {
                    thread2.Abort();
                }
                thread2 = null;
            }
            catch (Exception ex)
            {
                //에러 로그기록
            }
        }
    }
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e) :

이 부분은 Form1의 FormClosing 이벤트 핸들러다. 이 핸들러는 폼이 닫히기 직전에 호출된다. 여기서 sender는 이벤트를 발생시킨 객체를 나타내고, e는 이벤트와 관련된 추가 정보를 담고 있다.

try : 코드 블록 내에서 발생할 수 있는 예외를 처리하기 위해 try 블록 사용.

if (thread2.IsAlive) : thread2가 여전히 실행 중인지 확인. IsAlive 속성은 스레드가 아직 실행 중인 경우 true를 반환한다.

thread2.Abort() : thread2가 실행 중인 경우, Abort() 메서드를 호출하여 스레드를 중단시킨다. ※(이 메서드는 스레드를 즉시 중지하는 것이 아니라, 스레드가 중단될 수 있을 때 중단하도록 요청한다.)


thread2 = null; : thread2 참조를 null로 설정하여 더 이상 참조되지 않도록 한다. 이렇게 하면 가비지 컬렉터가 나중에 메모리를 정리할 수 있다.

catch (Exception ex) : try 블록 내의 코드가 예외를 발생시킬 경우, 이 catch 블록이 실행된다.

//에러 로그기록 : 일반적으로 이 부분에서 예외 정보를 로그 파일이나 콘솔에 기록하는 코드를 작성합니다. 이를 통해 나중에 문제를 분석하고 해결할 수 있다.

 

 

Reference : C#.NET 0.5년차~3년차(파트1)

※ 블로그에 있는 모든 강의와 책의 내용은 저작권자(출판사/저자,공동저자)에게 직접 허락을 받아 작성되었습니다.

https://www.inflearn.com/course/lecture?courseSlug=%EB%8B%B7%EB%84%B7-%EC%9C%88%ED%8F%BC-1&unitId=77892&tab=curriculum 

 

학습 페이지

 

www.inflearn.com

 

'C#' 카테고리의 다른 글

일반화 프로그래밍  (0) 2023.06.15
이벤트 생성/호출  (0) 2023.06.15
스레드 문제점 해결  (0) 2023.06.14
비동기, 동기  (0) 2023.06.14
스레드 동기화(lock,AutoResetEvent)  (0) 2023.06.13

20230615(목) 울산 맑은샘 헬스

  • 트레드밀 1시간
  • 레그 프레스 100KG 3SET  
  • 이너타이 60KG 3SET 50KG 3SET

'건강운동관리' 카테고리의 다른 글

헬스  (0) 2023.06.19
헬스  (0) 2023.06.16
헬스  (0) 2023.06.14
헬스  (0) 2023.06.13
헬스  (0) 2023.06.12

< 스택 메모리란? >

스택 메모리는 프로그램이 실행되는 동안 사용되는 메모리 영역 중 하나로, 함수 호출과 로컬 변수를 저장하는데 사용된다. "스택"이라는 이름은 데이터를 쌓아 올리는 형태로 관리되기 때문에 붙여진 이름이다. 함수가 호출될 때마다 새로운 스택 프레임이 생성되고, 함수가 종료되면 해당 스택 프레임이 제거된다.

출처 Wikipedia

< 로컬 변수는 어떻게 관리될까? >

로컬 변수란, 특정 코드 블록 내에서만 사용되는 변수를 말한다. 중괄호 {}로 둘러싸인 영역에서 선언된 변수들이 이에 해당한다.

using System;

namespace StackMemoryExample
{
    class Program
    {
        static void MyFunction()
        {
            int a = 10; // 로컬 변수
            Console.WriteLine(a);
        } // 여기서 'a'는 스택에서 제거된다.

        static void Main(string[] args)
        {
            MyFunction();
            // 여기서는 'a'에 접근할 수 없다.
        }
    }
}


MyFunction이라는 메서드 안에서 a라는 로컬 변수를 선언하고 있다. 이 메서드가 호출되면 a 변수가 스택 메모리에 할당된다. 그리고 메서드가 끝날 때 (닫는 중괄호 }를 만날 때), 스택에서 a 변수가 제거된다. 이 시점 이후로는 a 변수에 접근할 수 없다.

< 왜 이렇게 동작할까? >

스택 메모리는 효율적인 메모리 관리를 위해 이렇게 동작한다. 함수 호출이 끝나면 그 안에서 사용된 로컬 변수들은 더 이상 필요하지 않으므로, 메모리를 효율적으로 활용하기 위해 자동으로 해제되는 것이다.

 

 

Reference : https://en.wikipedia.org/wiki/Stack-based_memory_allocation

 

Stack-based memory allocation - Wikipedia

From Wikipedia, the free encyclopedia Form of computer memory allocation A typical stack, storing local data and call information for nested procedure calls (not necessarily nested procedures). This stack grows downward from its origin. The stack pointer p

en.wikipedia.org

 

'Developer 지식' 카테고리의 다른 글

JVM에 대한 이해 및 JRE,JDK  (0) 2023.06.06
스크립트 언어와 컴파일 언어의 차이점  (0) 2023.06.06
Process와 Thread  (0) 2023.06.06
자료구조와 알고리즘이란?  (0) 2023.06.02
Port kill 방법  (0) 2023.05.28

FastCampus의 AWS 강의를 열심히 수강했다. 강의에서는 다양한 AWS 서비스를 활용하는 방법에 대해 배웠고, 취미로 하고 있는 프로젝트에 적용을 해보고자 했었다. 강의가 모두 끝난 후, AWS의 모든 서비스를 정확하게 비활성화했다고 생각했다. 그런데, 계정에 16만원의 Billing Charge가 있었다.

[요금 청구 사유]

청구 내역을 살펴보니, 사용하지 않았다고 생각한 서비스에 대한 비용이 청구되었다. 먼저 AWS의 공식 문서를 참고하여 청구 관련 정책을 확인했다. 또한, Google에서 비슷한 사례를 검색해보았다, 다행히 나와 비슷한 사례가 많았다.

특히, https://velog.io/@kimphysicsman/AWS-%EC%9A%94%EA%B8%88-%EC%B2%AD%EA%B5%AC-%EA%B5%AC%EC%A0%9C%EB%B0%9B%EA%B8%B0 해당 블로그에서 지금 겪은 상황과 매우 비슷한 사례를 발견했다. 이를 참고로 하여 AWS Customer Support에 문의했고, 문제를 신속하게 해결해주었다.

이번 경험을 통해, 문제 상황에 직면했을 때 적극적으로 대응하고 필요한 정보를 탐색하는 것의 중요성을 다시 한번 깨달았다.

만약 비슷한 문제에 직면하셨다면, AWS 문서를 확인하고, 비슷한 사례를 검색하여 해결 방법을 찾는 것이 도움이 될 수 있겠다.

 

너무 당황해서 사진은 없으나, 중요한 것은 인스턴스 종료와 비활성화를 확인하고 또 확인해야 한다. 또 혹시 모르니 계정을 해지 했다. 계정을 새로 만들어서 정말 필요한 인스턴스만 쓰도록 해야겠다.

AWS Customer Support 팀에 감사드립니다.

※ 이 리뷰는 직접 구매하여 사용한 경험을 바탕으로 작성되었으며, 어떠한 광고나 수익 목적이 없습니다. 따라서 내용이 주관적일 수 있습니다.

Slid Application은 메모 작성을 도와주는 앱으로, 내게 큰 도움을 주었다. 사람들은 자연스럽게 망각하기 마련인데, 이를 최소화하고자 메모 작성을 습관화하고 있다. 이 때문에 Notion과 Slid Application을 활용하여 코딩 강의를 메모하거나 필요한 내용들을 기록하고 있다.

2023년 1월 20일 즈음, 유튜브 광고를 통해 Slid를 처음 알게 되었다. 그 전까지는 주로 Notion을 사용하고 있었으나, Slid가 갖고 있는 Notion이 제공하지 않는 독특한 기능들 때문에 현재는 두 앱을 병행하여 사용하고 있다. (Notion에 대한 리뷰는 다음 기회에 작성할 예정이다.)

< Slid의 장점 >
Slid를 사용하면서 느낀 점 중 하나는 그 사용성이다. 과거, 2022년 11월 21일부터 2023년 5월 중순까지, 나는 아침 6시부터 밤 12시까지 거의 밥도 먹지 않고 공부를 했었다. Notion을 사용하면서 인터페이스가 나에게는 다소 복잡해 보였다. 그런데 Slid를 발견하고 사용해보니, 폴더 형식이 간단하고 색상도 지정할 수 있어서, 나만의 중요도를 표시하는 데 편리했다. 또한 인터페이스가 친숙하게 느껴져 빠르게 메모를 작성할 수 있었고, 이를 통해 강의나 공부한 내용을 체계적으로 기록하고 복습할 수 있었다.

특히 흥미로웠던 기능 중 하나는 음성을 텍스트로 변환해주는 기능이었다. 이 기능은 하루에 많은 양의 메모를 작성할 때 피로를 줄여주는 데 큰 도움이 되었다. 또한 60초 동안의 영상 녹화 기능도 메모 작성에 있어 편리했다.

추가적으로, Slid는 웹 사이트 뿐만 아니라 스마트폰에서도 사용할 수 있어서 이동 중에도 메모를 복습하는 데 유용했다.

< Slid의 단점 >
그러나 Slid의 음성을 텍스트로 변환하는 기능이 나의 현재 회원 등급에서는 사용할 수 없어 아쉬웠다.

< Slid 팀과의 인터뷰 및 대표님과의 만남 >
4월 말쯤, Slid 팀으로부터 연락이 왔고 인터뷰를 요청받았다. 이 인터뷰는 Slid의 우수 사용자들을 대상으로 진행되었다.

그 당시에 Slid를 하루에 18시간씩 사용하면서 여러 궁금증이 있었는데 이 기회를 통해 필요한 기능이나 궁금증을 직접 팀에게 전달할 수 있어 좋았다.

또한, Slid의 대표님과도 만날 기회가 주어졌다. 대표님과의 만남은 나에게 큰 동기부여가 되었고, 많은 것을 배울 수 있었다. 이 경험을 통해 더 열심히 노력하여 선한 영향력을 가진 개발자가 되겠다고 다짐했다.

 

 

폴더 안에 여러가지 메모들을 넣을 수 있다. 즉 폴더는 주제라고 생각하면 된다. 또한 색깔을 내마음대로 해서 중요도를 표시 할 수 있다.
밑의 108개의 노트는 정리해야되는데... 너무 많아서 아무리 정리하고 정리해도 끝이 없기도 하고, 검색하는게 편해서 몇 개 옮기다가 방치 상태. 저것들 날 잡고 정리를 해야겠다.

 

멀티스레딩을 사용하면 한 프로세스 내에서 여러 개의 작업을 동시에 처리할 수 있다. 하지만 이런 스레드들을 잘 관리하지 않으면 리소스가 해제되지 않는 문제가 발생할 수 있다.

 

이는 시스템 자원을 불필요하게 점유하게 되어 프로그램의 성능을 저하시키거나 메모리 누수 같은 문제를 발생시킬 수 있다.

< 스레드의 자원을 제대로 해제하는 두 가지 방법 >

[Background 속성 이용]
스레드는 기본적으로 Foreground 스레드로 생성된다. 때문에 메인(UI) 스레드가 종료되어도 해당 스레드는 계속 실행된다. 하지만 Background 스레드로 설정하면 메인 스레드가 종료될 때 해당 스레드도 함께 종료되어 자원을 해제하게 된다.

 Thread.IsBackground = true;를 통해 해당 스레드를 Background 스레드로 설정할 수 있다.이렇게 하면 해당 스레드가 프로그램이 종료되는 시점에서 함께 종료되도록 한다.

[Form Closing]
Form이 종료되는 시점에 작동하는 이벤트인 Form Closing을 이용해 스레드의 자원을 해제할 수도 있다. 만약 Form이 닫히는 시점에 생성된 스레드가 아직 실행 중이라면 해당 스레드를 종료하고 자원을 해제하는 코드를 작성한다. 이를 통해 스레드가 더 이상 필요하지 않은 시점에 정확하게 스레드를 종료하고 자원을 회수할 수 있다.

< 실습 >

아래와 같이 코드를 작성하고 솔루션 빌드 후, 실행을 하고 Form1 창을 닫았다. 그러면 정말 종료가 된 것일까?

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        Thread th = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //쓰레드 자원할당
            th = new Thread(new ThreadStart(methodStart));
            th.Start();//쓰레드가 실행 
        }
        private void methodStart()
        { 
          while(true) 
            { 
                //1초씩 쓰레드가 멈추도록 
                Thread.Sleep(1000);

            }
        }
    }
}

위의 코드를 실행 하고, Form1 창을 닫아 보았다.

 

창을 닫으면, WinFormsApp1이 실행 종료가 된 줄 알았는데 작업관리자에 가보니, Background에서 여전히 실행 중인 것을 알 수 있다.

즉, 아래의 스레드 부분이 계속 실행이 되고 있다는 것이다.

이럴 경우 작업관리자에서 직접 프로세스를 종료를 해줘야한다. 이러한 현상이 일어나는 이유는 스레드 리소스를 해제를 안했다는 것이다.

 

이때 Thread.IsBackground = true;를 사용하게 되면, 창을 닫으면 프로세스도 같이 종료가 되는 것을 확인할 수 있다.

namespace WinFormsApp1
{
    public partial class Form1 : Form
    {
        Thread th = null;

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //쓰레드 자원할당
            th = new Thread(new ThreadStart(methodStart));
            th.IsBackground = true;
            th.Start();//쓰레드가 실행 
        }
        private void methodStart()
        { 
          while(true) 
            { 
                //1초씩 쓰레드가 멈추도록 
                Thread.Sleep(1000);

            }
        }
    }
}

※ 주의 사항 Form1에서 Form2를 생성하고, Form2를 실행하도록 하고,

Form2에 th.IsBackground = true;를 설정하면, 스레드가 종료가 될 줄 알았는데, 종료가 안된다.

이유는  UIThread 즉, Program.cs에서 Form2로 변경해야지만, 삭제가 된다.

 

 이렇게 IsBackground를 사용하기 보다는 다시 new Form2를 Form1으로 원상복구 한 뒤,

Form2가 닫히면, 스레드가 종료되도록 하고 싶다면 이때 Form Closing 방법을 쓸 수 있다. 

 

Reference : C#.NET 0.5년차~3년차(파트1)

이 블로그의 모든 내용은 원작자와 출판사로부터 허락을 받아 작성되었습니다.

https://www.inflearn.com/course/lecture?courseSlug=%EB%8B%B7%EB%84%B7-%EC%9C%88%ED%8F%BC-1&unitId=77888&tab=curriculum 

 

'C#' 카테고리의 다른 글

이벤트 생성/호출  (0) 2023.06.15
크로스 스레드  (0) 2023.06.15
비동기, 동기  (0) 2023.06.14
스레드 동기화(lock,AutoResetEvent)  (0) 2023.06.13
멀티스레드  (0) 2023.06.13

20230614(수) 울산 맑은샘 헬스

 

 

  • 레그 익스텐션 80KG 10SET
  • 인클라인 트레드밀 20분
  • 자전거 10분 

'건강운동관리' 카테고리의 다른 글

헬스  (0) 2023.06.19
헬스  (0) 2023.06.16
헬스  (0) 2023.06.15
헬스  (0) 2023.06.13
헬스  (0) 2023.06.12

+ Recent posts